<template>
  <view class="container">
    <!-- 顶部标签栏（固定在顶部） -->
    <view class="tab-bar fixed">
      <view class="back-btn" @click="goBack">
        <FeatherIcon name="chevron-left" size="24" color="#000" />
      </view>
      <view class="tab-wrapper">
        <view
          class="tab-item"
          :class="{ active: currentTab === 0 }"
          @click="switchTab(0)"
        >
          <text>正文</text>
        </view>
        <view
          class="tab-item"
          :class="{ active: currentTab === 1 }"
          @click="switchTab(1)"
        >
          <text>评论 ({{ article ? article.articleCommentCount : 0 }})</text>
        </view>
      </view>
    </view>

    <!-- 内容区占位，补偿固定标签栏的高度 -->
    <view class="tab-placeholder"></view>

    <!-- 可滑动内容区域 -->
    <swiper
      class="content-swiper"
      :current="currentTab"
      @change="swiperChange"
      :style="{ height: contentHeight + 'px' }"
    >
      <!-- 文章正文页 -->
      <swiper-item>
        <scroll-view
          scroll-y
          style="padding-top: 30px"
          class="article-scroll"
          @scrolltolower="onReachBottom"
          :style="{ height: contentHeight + 'px' }"
        >
          <view class="article-detail" v-if="article">
            <!-- 文章头部 -->
            <view class="article-header">
              <text class="article-title">{{ article.articleTitle }}</text>

              <view
                class="article-meta"
                @click="navigateToUserDetail(article.articleAuthor.userName)"
              >
                <view class="author-info">
                  <image
                    class="author-avatar"
                    :src="article.articleAuthor.userAvatarURL"
                    mode="aspectFill"
                  ></image>
                  <view class="author-detail">
                    <text class="author-name">{{
                      article.articleAuthor.userNickname ||
                      article.articleAuthor.userName
                    }}</text>
                    <text class="publish-time">{{
                      formatDate(article.articleCreateTimeStr)
                    }}</text>
                  </view>
                </view>

                <view class="article-stats">
                  <view class="stat-item">
                    <FeatherIcon name="eye" size="16" color="#999" />
                    <text class="stat-count">{{
                      article.articleViewCount
                    }}</text>
                  </view>
                  <view
                    class="stat-item reader-info"
                    v-if="onlineCount > 0"
                    :class="{ active: showOnlineChange }"
                  >
                    <view class="status-dot"></view>
                    <text class="stat-count">{{ onlineCount }}人正在阅读</text>
                  </view>
                </view>
              </view>

              <!-- 添加在线人数变化提示 -->
              <view class="online-change-tip" v-if="showOnlineChange">
                <text>{{ onlineChangeText }}</text>
              </view>

              <!-- 文章标签 -->
              <scroll-view
                scroll-x
                class="tags-scroll"
                v-if="
                  article.articleTagObjs && article.articleTagObjs.length > 0
                "
              >
                <view class="article-tags">
                  <text
                    class="tag"
                    v-for="(tag, tagIndex) in article.articleTagObjs"
                    :key="tag.oId"
                    @click.stop="navigateToTagArticles(tag)"
                    >{{ tag.tagTitle }}</text
                  >
                </view>
              </scroll-view>
            </view>

            <!-- 文章内容 -->
            <view class="article-content" @tap="handleContentTap">
              <template
                v-for="(node, index) in parsedContent"
                :key="node.key || index"
              >
                <template v-if="node.type === 'video'">
                  <view
                    class="video-container"
                    @click="playVideo('video-' + node.index)"
                  >
                    <video
                      :src="node.src"
                      :id="'video-' + node.index"
                      :poster="videoPoster"
                      controls
                      class="article-video"
                      :key="node.key"
                      :style="{
                        height: node.height === 'auto' ? '400rpx' : node.height,
                      }"
                      show-center-play-btn="true"
                      show-play-btn="true"
                      custom-cache="false"
                      show-fullscreen-btn="true"
                      enable-progress-gesture="true"
                      @error="handleVideoError"
                      @play="handleVideoPlay"
                      @loadedmetadata="handleVideoLoaded($event, node.index)"
                    ></video>
                    <!-- 视频加载指示器 - 使用节点的索引 -->
                    <view
                      class="video-loading"
                      v-if="
                        !videoLoadError[node.index] && !videoLoaded[node.index]
                      "
                    >
                      <view class="video-loading-spinner"></view>
                      <text class="video-loading-text"
                        >视频加载中，点击播放</text
                      >
                      <view
                        class="video-force-play"
                        @click.stop="forcePlayVideo(node.index)"
                        >点击播放</view
                      >
                    </view>
                    <!-- 视频加载中或错误时显示的覆盖层 -->
                    <view
                      class="video-overlay"
                      v-if="videoLoadError[node.index]"
                    >
                      <view class="video-overlay-content">
                        <text class="video-error-text"
                          >视频加载失败，点击重试</text
                        >
                        <view
                          class="video-retry-btn"
                          @click.stop="retryLoadVideo(node.index)"
                          >重试</view
                        >
                      </view>
                    </view>
                    <!-- 播放按钮 -->
                    <view
                      class="video-play-button"
                      @click.stop="playVideo('video-' + node.index)"
                      v-if="
                        !videoPlaying[node.index] && videoLoaded[node.index]
                      "
                    >
                      <view class="video-play-icon"></view>
                    </view>
                  </view>
                </template>
                <template v-else-if="node.type === 'text'">
                  <rich-text :nodes="node.content"></rich-text>
                </template>
              </template>
            </view>

            <!-- 打赏可见区域 -->
            <view
              class="reward-section"
              v-if="
                article.articleRewardContent &&
                article.articleRewardContent !== '\n'
              "
            >
              <view class="reward-content" v-if="rewardContentVisible">
                <view class="reward-body">
                  <rich-text
                    :nodes="formattedRewardContent"
                    @click="handleContentTap"
                  ></rich-text>
                </view>
                <view class="reward-footer">
                  <text class="reward-footer-text"
                    >{{ article.rewardedCnt || 0 }}人打赏</text
                  >
                </view>
              </view>
              <view class="reward-locked" v-else>
                <view class="reward-lock-icon">
                  <FeatherIcon name="lock" size="32" color="#ff8000" />
                </view>
                <view class="reward-info">
                  <text class="reward-text">此内容需打赏后可见</text>
                  <text class="reward-point"
                    >{{ article.articleRewardPoint }} 积分</text
                  >
                  <text class="reward-count"
                    >{{ article.rewardedCnt || 0 }}人已打赏</text
                  >
                </view>
                <view class="reward-btn" @click="showRewardConfirm"
                  >打赏可见</view
                >
              </view>
            </view>

            <!-- 优质评论 -->
            <view class="article-comments" v-if="niceComments.length > 0">
              <view class="section-header">
                <text class="section-title">优质评论</text>
              </view>

              <view class="comment-list">
                <view
                  class="comment-item preview-comment"
                  v-for="(comment, niceIndex) in niceComments"
                  :key="comment.oId"
                >
                  <view class="comment-body">
                    <view class="comment-header">
                      <image
                        class="commenter-avatar"
                        :src="
                          comment.commentAuthorThumbnailURL ||
                          (comment.commenter
                            ? comment.commenter.userAvatarURL
                            : '')
                        "
                        mode="aspectFill"
                      ></image>
                      <view class="comment-meta">
                        <text class="commenter-name">{{
                          comment.commentAuthorNickName +
                            "(" +
                            comment.commenter.userName +
                            ")" ||
                          comment.commentAuthorName ||
                          (comment.commenter
                            ? comment.commenter.userNickname ||
                              comment.commenter.userName
                            : "")
                        }}</text>
                        <!-- 添加作者标签 -->
                        <text
                          class="comment-tag author-tag"
                          v-if="isArticleAuthor(comment.commenter?.userName)"
                          >作者</text
                        >
                      </view>
                    </view>

                    <view
                      class="comment-content"
                      @tap="handleContentTap"
                      @click="handleCommentClick(comment)"
                    >
                      <rich-text
                        :nodes="formattedCommentContent(comment)"
                      ></rich-text>
                    </view>

                    <view class="comment-footer">
                      <view class="comment-time">
                        <text>{{
                          comment.timeAgo ||
                          formatTime(comment.commentCreateTime)
                        }}</text>
                        <text
                          class="reply-text"
                          @click="handleReplyComment(comment)"
                          >回复</text
                        >
                      </view>
                      <view class="comment-actions">
                        <view
                          class="action-item"
                          @click="handleLikeComment(comment)"
                        >
                          <FeatherIcon
                            :name="comment.hasLiked ? 'thumbs-up' : 'thumbs-up'"
                            size="16"
                            :color="comment.hasLiked ? '#ff8000' : '#999'"
                          />
                          <text class="action-text">{{
                            comment.commentGoodCnt || 0
                          }}</text>
                        </view>
                        <view
                          class="action-item"
                          @click="handleThankComment(comment)"
                        >
                          <FeatherIcon name="heart" size="16" color="#999" />
                          <text class="action-text">{{
                            comment.commentThankCnt || 0
                          }}</text>
                        </view>
                      </view>
                    </view>

                    <!-- 移动到评论时间下方的标签区域 -->
                    <view class="comment-tags">
                      <text class="comment-tag nice-tag">优质评论</text>
                      <text
                        class="comment-tag first-tag"
                        v-if="niceIndex === 0 && niceComments.length > 1"
                        >首赞</text
                      >
                      <text
                        class="comment-tag most-liked-tag"
                        v-if="isTopLikedInNice(comment)"
                        >最多点赞</text
                      >
                      <text
                        class="comment-tag most-thanked-tag"
                        v-if="isTopThankedInNice(comment)"
                        >最多感谢</text
                      >
                    </view>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </scroll-view>
      </swiper-item>

      <!-- 评论页 -->
      <swiper-item>
        <scroll-view
          scroll-y
          style="padding-top: 30px"
          class="comment-scroll"
          @scrolltolower="loadMoreComments"
          :style="{ height: contentHeight + 'px' }"
        >
          <view class="comment-section">
            <view class="section-header">
              <text class="section-title"
                >评论 ({{ article ? article.articleCommentCount : 0 }})</text
              >
              <view class="sort-toggle" @click="toggleSortOrder">
                <text class="sort-text">{{
                  isDescOrder ? "最新" : "最早"
                }}</text>
                <FeatherIcon name="chevron-down" size="16" color="#666" />
              </view>
            </view>

            <view class="comment-list" v-if="comments.length > 0">
              <!-- 主评论 -->
              <view
                class="comment-item"
                v-for="(comment, index) in comments"
                :key="comment.oId"
              >
                <view class="comment-body">
                  <view
                    class="comment-header"
                    @click="navigateToUserDetail(comment.commenter.userName)"
                  >
                    <image
                      class="commenter-avatar"
                      :src="
                        comment.commentAuthorThumbnailURL ||
                        (comment.commenter
                          ? comment.commenter.userAvatarURL
                          : '')
                      "
                      mode="aspectFill"
                    ></image>
                    <view class="comment-meta">
                      <text class="commenter-name">{{
                        comment.commentAuthorNickName +
                          "(" +
                          comment.commenter.userName +
                          ")" ||
                        comment.commentAuthorName ||
                        (comment.commenter
                          ? comment.commenter.userNickname ||
                            comment.commenter.userName
                          : "")
                      }}</text>
                      <!-- 添加作者标签 -->
                      <text
                        class="comment-tag author-tag"
                        v-if="isArticleAuthor(comment.commenter?.userName)"
                        >作者</text
                      >
                    </view>
                  </view>

                  <view
                    class="comment-content"
                    @tap="handleContentTap"
                    @click="handleCommentClick(comment)"
                  >
                    <rich-text
                      :nodes="formattedCommentContent(comment)"
                    ></rich-text>
                  </view>

                  <view class="comment-footer">
                    <view class="comment-time">
                      <text>{{
                        comment.timeAgo || formatTime(comment.commentCreateTime)
                      }}</text>
                      <text
                        class="reply-text"
                        @click="handleReplyComment(comment)"
                        >回复</text
                      >
                    </view>
                    <view class="comment-actions">
                      <view
                        class="action-item"
                        @click="handleLikeComment(comment)"
                      >
                        <FeatherIcon
                          :name="comment.hasLiked ? 'thumbs-up' : 'thumbs-up'"
                          size="16"
                          :color="comment.hasLiked ? '#ff8000' : '#999'"
                        />
                        <text class="action-text">{{
                          comment.commentGoodCnt || 0
                        }}</text>
                      </view>
                      <view
                        class="action-item"
                        @click="handleThankComment(comment)"
                      >
                        <FeatherIcon name="heart" size="16" color="#999" />
                        <text class="action-text">{{
                          comment.commentThankCnt || 0
                        }}</text>
                      </view>
                    </view>
                  </view>

                  <!-- 评论标签区域：移动到评论footer之后 -->
                  <view
                    class="comment-tags"
                    v-if="
                      comment.isFirstComment ||
                      isMostLikedComment(comment) ||
                      isMostThankedComment(comment) ||
                      comment.containsVideo
                    "
                  >
                    <text
                      class="comment-tag first-tag"
                      v-if="comment.isFirstComment"
                      >首评</text
                    >
                    <text
                      class="comment-tag most-liked-tag"
                      v-if="isMostLikedComment(comment)"
                      >最多点赞</text
                    >
                    <text
                      class="comment-tag most-thanked-tag"
                      v-if="isMostThankedComment(comment)"
                      >最多感谢</text
                    >
                    <text
                      class="comment-tag video-tag"
                      v-if="comment.containsVideo"
                      >包含视频</text
                    >
                  </view>

                  <!-- 回复评论 -->
                  <view
                    class="reply-list"
                    v-if="comment.replies && comment.replies.length > 0"
                  >
                    <!-- 显示可见的回复 -->
                    <view
                      class="reply-item"
                      v-for="(reply, replyIndex) in getVisibleReplies(comment)"
                      :key="reply.oId"
                    >
                      <view class="reply-body">
                        <view
                          class="comment-header"
                          @click="
                            navigateToUserDetail(reply.commenter.userName)
                          "
                        >
                          <image
                            class="commenter-avatar"
                            :src="
                              reply.commentAuthorThumbnailURL ||
                              (reply.commenter
                                ? reply.commenter.userAvatarURL
                                : '')
                            "
                            mode="aspectFill"
                          ></image>
                          <view class="comment-meta">
                            <text class="commenter-name">{{
                              reply.commentAuthorNickName ||
                              reply.commentAuthorName ||
                              (reply.commenter
                                ? reply.commenter.userNickname ||
                                  reply.commenter.userName
                                : "")
                            }}</text>
                            <!-- 添加作者标签 -->
                            <text
                              class="comment-tag author-tag"
                              v-if="isArticleAuthor(reply.commenter?.userName)"
                              >作者</text
                            >
                            <!-- 添加回复对象，只有回复的回复（不是直接回复主评论的）才显示 -->
                            <text
                              class="reply-to"
                              v-if="
                                reply.commentOriginalCommentId &&
                                reply.commentOriginalCommentId !== comment.oId
                              "
                            >
                              回复
                              <text class="reply-target-name">{{
                                getReplyTargetName(reply, comment)
                              }}</text>
                            </text>
                          </view>
                        </view>
                        <view class="reply-item-content">
                          <rich-text
                            :nodes="formattedCommentContent(reply)"
                          ></rich-text>
                        </view>
                        <view class="reply-item-footer">
                          <view class="reply-item-time">
                            <text>{{
                              reply.timeAgo ||
                              formatTime(reply.commentCreateTime)
                            }}</text>
                            <text
                              class="reply-text"
                              @click="handleReplyComment(reply)"
                              >回复</text
                            >
                          </view>
                          <view class="reply-item-actions">
                            <view
                              class="action-item"
                              @click="handleLikeComment(reply)"
                            >
                              <FeatherIcon
                                :name="
                                  reply.hasLiked ? 'thumbs-up' : 'thumbs-up'
                                "
                                size="16"
                                :color="reply.hasLiked ? '#ff8000' : '#999'"
                              />
                              <text class="action-text">{{
                                reply.commentGoodCnt || 0
                              }}</text>
                            </view>
                            <view
                              class="action-item"
                              @click="handleThankComment(reply)"
                            >
                              <FeatherIcon
                                name="heart"
                                size="16"
                                color="#999"
                              />
                              <text class="action-text">{{
                                reply.commentThankCnt || 0
                              }}</text>
                            </view>
                          </view>
                        </view>
                        <!-- 回复评论标签 -->
                        <view
                          class="comment-tags reply-tags"
                          v-if="
                            reply.isFirstReply ||
                            isTopLikedReply(reply, comment) ||
                            isTopThankedReply(reply, comment)
                          "
                        >
                          <text
                            class="comment-tag most-liked-tag"
                            v-if="isTopLikedReply(reply, comment)"
                            >最多点赞</text
                          >
                          <text
                            class="comment-tag most-thanked-tag"
                            v-if="isTopThankedReply(reply, comment)"
                            >最多感谢</text
                          >
                        </view>
                      </view>
                    </view>

                    <!-- 添加展开/折叠按钮 -->
                    <view
                      class="replies-toggle"
                      v-if="comment.replies.length > 2"
                      @click="toggleReplies(comment.oId)"
                    >
                      <FeatherIcon
                        :name="
                          isExpanded(comment.oId)
                            ? 'chevron-up'
                            : 'chevron-down'
                        "
                        size="16"
                        color="#999"
                      />
                      <text class="toggle-text">
                        {{
                          isExpanded(comment.oId)
                            ? "收起回复"
                            : `展开全部 ${comment.replies.length} 条回复`
                        }}
                      </text>
                    </view>
                  </view>
                </view>
              </view>
            </view>

            <view class="empty-comment" v-else-if="!isLoadingComments">
              <FeatherIcon name="message-square" size="48" color="#ddd" />
              <text>暂无评论，快来发表第一条评论吧~</text>
            </view>

            <view class="loading-comment" v-else>
              <view class="loading-spinner"></view>
              <text>评论加载中...</text>
            </view>

            <!-- 加载更多评论 -->
            <view
              class="load-more"
              v-if="comments.length > 0 && hasMoreComments"
              @click="loadMoreComments"
            >
              <text
                class="loading-text"
                :class="{ breathing: isLoadingComments }"
              >
                {{ isLoadingComments ? "加载中..." : "点击加载更多评论" }}
              </text>
            </view>
            <view
              class="no-more-text"
              v-if="!hasMoreComments && comments.length > 0"
            >
              没有更多评论啦~
            </view>
          </view>
        </scroll-view>
      </swiper-item>
    </swiper>

    <!-- 底部操作栏 -->
    <view class="action-footer">
      <view class="action-input" @click="showCommentInput">
        <FeatherIcon name="message-circle" size="20" color="#999" />
        <text class="input-placeholder">评论一下，快乐一天</text>
      </view>

      <view class="action-buttons">
        <view class="action-btn" @click="handleLike">
          <FeatherIcon
            :name="hasLiked ? 'thumbs-up' : 'thumbs-up'"
            size="24"
            :color="hasLiked ? '#ff8000' : '#666'"
          />
          <text class="action-count">{{
            article ? article.articleGoodCnt : 0
          }}</text>
        </view>
        <view class="action-btn" @click="handleThank">
          <FeatherIcon
            :name="hasThanked ? 'heart' : 'heart'"
            size="24"
            :color="hasThanked ? '#ff8000' : '#666'"
          />
          <text class="action-count">{{
            article ? article.articleThankCnt : 0
          }}</text>
        </view>
        <view class="action-btn" @click="switchTab(1)">
          <FeatherIcon name="message-circle" size="24" color="#666" />
          <text class="action-count">{{
            article ? article.articleCommentCount : 0
          }}</text>
        </view>

        <!-- 添加置顶按钮 - 仅作者可见 -->
        <view
          class="action-btn"
          v-if="article && isCurrentUserAuthor()"
          @click="showStickConfirm"
        >
          <FeatherIcon
            name="arrow-up-circle"
            size="24"
            :color="isArticleSticky ? '#ff8000' : '#666'"
          />
          <view class="action-count-wrapper">
            <text class="action-count">{{
              isArticleSticky ? "置顶中" : "置顶"
            }}</text>
          </view>
        </view>
      </view>
    </view>

    <!-- 评论输入框弹层 -->
    <view
      class="comment-modal"
      v-if="showCommentBox"
      @click.self="hideCommentInput"
    >
      <view
        class="comment-input-container"
        :style="{ bottom: keyboardHeight + 'px' }"
      >
        <textarea
          class="comment-input"
          v-model="commentContent"
          :placeholder="
            replyToComment
              ? `回复 ${getCommentAuthorName(replyToComment)}`
              : '写下你的评论...'
          "
          :placeholder-style="'color: #999;'"
          :focus="commentFocus"
          maxlength="1000"
          auto-height
          :adjust-position="false"
          @focus="onFocus"
          @blur="onBlur"
        ></textarea>
        <view class="comment-toolbar">
          <view class="toolbar-left">
            <view class="toolbar-item" @click="handleImageUpload">
              <FeatherIcon name="image" size="24" color="#666" />
            </view>
            <view class="toolbar-item" @click="handleEmoji">
              <FeatherIcon name="smile" size="24" color="#666" />
            </view>
          </view>
          <view class="toolbar-right">
            <view class="cancel-btn" @click="hideCommentInput">取消</view>
            <view
              class="submit-btn"
              :class="{
                'submit-btn-disabled': !commentContent.trim() || submitting,
              }"
              @click="submitComment"
            >
              {{ submitting ? "提交中..." : "发表" }}
            </view>
          </view>
        </view>

        <!-- 表情面板 -->
        <view class="emoji-panel" v-if="showEmojiPanel" @click.stop>
          <view class="emoji-header">
            <text class="emoji-title">表情</text>
            <view class="emoji-close" @click="showEmojiPanel = false">
              <FeatherIcon name="x" size="24" color="#666" />
            </view>
          </view>
          <view class="emoji-tabs">
            <view
              class="emoji-tab"
              :class="{ active: emojiTabIndex === 0 }"
              @click="switchEmojiTab(0)"
            >
              <text>默认表情</text>
            </view>
            <view
              class="emoji-tab"
              :class="{ active: emojiTabIndex === 1 }"
              @click="switchEmojiTab(1)"
            >
              <text>我的表情</text>
            </view>
          </view>
          <swiper
            class="emoji-swiper"
            :current="emojiTabIndex"
            @change="onEmojiTabChange"
            :duration="300"
          >
            <!-- 默认表情 -->
            <swiper-item>
              <scroll-view scroll-y class="emoji-scroll">
                <view class="emoji-content">
                  <view class="emoji-list" v-if="defaultEmoticons.length > 0">
                    <view
                      class="emoji-item"
                      v-for="(emoji, index) in defaultEmoticons"
                      :key="'default-' + index"
                      @click="selectEmoji(emoji.value)"
                    >
                      <template
                        v-if="emoji.value && emoji.value.startsWith('http')"
                      >
                        <image
                          class="emoji-image"
                          :src="emoji.value"
                          mode="aspectFit"
                        ></image>
                      </template>
                      <template v-else>
                        <text class="emoji-text">{{ emoji.value }}</text>
                      </template>
                    </view>
                  </view>

                  <!-- 加载中 -->
                  <view class="emoji-loading" v-if="isLoadingEmoticons">
                    <text>加载表情中...</text>
                  </view>

                  <!-- 空状态 -->
                  <view
                    class="emoji-empty"
                    v-else-if="defaultEmoticons.length === 0"
                  >
                    <text>暂无默认表情</text>
                  </view>
                </view>
              </scroll-view>
            </swiper-item>

            <!-- 用户表情包 -->
            <swiper-item>
              <scroll-view scroll-y class="emoji-scroll">
                <view class="emoji-content">
                  <view class="emoji-list" v-if="customEmoticons.length > 0">
                    <view
                      class="emoji-item"
                      v-for="(emoji, index) in customEmoticons"
                      :key="'custom-' + index"
                      @click="selectEmoji(emoji)"
                    >
                      <image
                        class="emoji-image"
                        :src="emoji"
                        mode="aspectFit"
                      ></image>
                    </view>
                  </view>

                  <!-- 加载中 -->
                  <view class="emoji-loading" v-if="isLoadingEmoticons">
                    <text>加载表情中...</text>
                  </view>

                  <!-- 空状态 -->
                  <view
                    class="emoji-empty"
                    v-else-if="customEmoticons.length === 0"
                  >
                    <text>暂无自定义表情</text>
                  </view>
                </view>
              </scroll-view>
            </swiper-item>
          </swiper>
        </view>
      </view>
    </view>

    <!-- 登录提示 -->
    <view class="login-modal" v-if="!isLoggedIn && showLoginTip">
      <view class="login-content">
        <text class="login-title">提示</text>
        <text class="login-message">请登录后进行操作</text>
        <view class="login-buttons">
          <text class="cancel-login" @click="showLoginTip = false">取消</text>
          <text class="confirm-login" @click="goToLogin">去登录</text>
        </view>
      </view>
    </view>

    <!-- 感谢确认弹窗 -->
    <view class="thank-modal" v-if="showThankConfirm">
      <view class="thank-content">
        <view class="thank-body">
          <text class="thank-message">确定赠送</text>
          <text class="thank-points"
            >{{ thankTargetType === "article" ? "20" : "15" }} 积分</text
          >
          <text class="thank-message"
            >给{{
              thankTargetType === "article" ? "该帖作者" : "该评论作者"
            }}以表谢意？</text
          >
        </view>
        <view class="thank-buttons">
          <view class="thank-btn cancel" @click="showThankConfirm = false"
            >取消</view
          >
          <view class="thank-btn confirm" @click="confirmThank">确定</view>
        </view>
      </view>
    </view>

    <!-- 打赏确认弹窗 -->
    <view class="reward-modal" v-if="showRewardDialog">
      <view class="reward-modal-content">
        <view class="reward-modal-title">打赏确认</view>
        <view class="reward-modal-body">
          <text class="reward-modal-text">确定要打赏</text>
          <text class="reward-modal-point"
            >{{ article ? article.articleRewardPoint : 0 }} 积分</text
          >
          <text class="reward-modal-text">给该帖子作者？</text>
        </view>
        <view class="reward-modal-buttons">
          <view class="reward-modal-cancel" @click="showRewardDialog = false"
            >取消</view
          >
          <view class="reward-modal-confirm" @click="confirmReward">确定</view>
        </view>
      </view>
    </view>

    <!-- 图片预览模态框 -->
    <view class="image-preview-modal" v-if="showImagePreview">
      <view class="image-preview-mask" @tap.stop="closeImagePreview"></view>
      <ImageViewer
        :value="[{ url: previewImageUrl }]"
        :editable="false"
        :itemSize="0"
        @preview-close="closeImagePreview"
      />
    </view>
    <!-- 置顶确认弹窗 -->
    <view class="stick-modal" v-if="showStickDialog">
      <view class="stick-modal-content">
        <view class="stick-modal-title">置顶确认</view>
        <view class="stick-modal-body">
          <text class="stick-modal-text">确定要消费</text>
          <text class="stick-modal-point">100 积分</text>
          <text class="stick-modal-text">来置顶该帖子吗？</text>
          <text class="stick-duration">置顶时间: 30分钟</text>
        </view>
        <view class="stick-modal-buttons">
          <view class="stick-modal-cancel" @click="showStickDialog = false"
            >取消</view
          >
          <view class="stick-modal-confirm" @click="confirmStick">确定</view>
        </view>
      </view>
    </view>
    <activity-tip
      :visible="showTip"
      :points="tipPoints"
      :description="tipDescription"
    />
  </view>
</template>

<script setup>
import {
  ref,
  reactive,
  onMounted,
  nextTick,
  onUnmounted,
  computed,
  onActivated,
} from "vue";
import {
  formatDate,
  timeAgo,
  showLoading,
  hideLoading,
  showError,
  showSuccess,
} from "@/utils/common.js";
import api from "@/api";
import { isLoggedIn, getApiKey } from "@/api/request";
import FeatherIcon from "@/components/FeatherIcon.vue";
import ActivityTip from "@/components/ActivityTip.vue";
import activityManager from "@/utils/activityManager";
import ImageViewer from "@/components/ImageViewer.vue"; // 导入ImageViewer组件
import { chooseAndUploadImage } from "@/utils/upload";

// 获取文章ID
const articleId = ref("");
// 文章详情数据
const article = ref(null);
// 评论列表
const comments = ref([]);
// 是否有更多评论
const hasMoreComments = ref(false);
// 评论页码
const commentPage = ref(1);
// 总页数
const totalPages = ref(1);
// 评论内容
const commentContent = ref("");
// 评论输入框焦点
const commentFocus = ref(false);
// 是否提交中
const submitting = ref(false);
// 点赞状态
const hasLiked = ref(false);
// 是否显示评论框
const showCommentBox = ref(false);
// 是否显示登录提示
const showLoginTip = ref(false);
// 回复的评论
const replyToComment = ref(null);
// 当前显示的tab
const currentTab = ref(0);
// 内容区域高度（动态计算）
const contentHeight = ref(0);
// 滚动位置
const scrollTop = ref(0);
// 软键盘高度
const keyboardHeight = ref(0);
// 是否已感谢
const hasThanked = ref(false);
// 优质评论
const niceComments = ref([]);
// 是否正在加载评论
const isLoadingComments = ref(false);
// 是否显示感谢确认
const showThankConfirm = ref(false);
// 感谢目标类型
const thankTargetType = ref("");
// 感谢目标ID
const thankTargetId = ref("");
// 图片预览相关变量
const previewImageUrl = ref("");
const showImagePreview = ref(false);
// 表情包相关
const defaultEmoticons = ref([]); // 默认表情
const customEmoticons = ref([]); // 用户表情包
const showEmojiPanel = ref(false); // 是否显示表情面板
const isLoadingEmoticons = ref(false); // 是否正在加载表情
// 添加评论排序方式
const isDescOrder = ref(true); // 默认为倒序（最新的在前）
// 在script定义部分添加当前激活的表情标签
const emojiTabIndex = ref(0); // 当前激活的表情标签索引，0:默认表情，1:我的表情
// 视频加载错误状态
const videoLoadError = ref({});
// 视频播放状态
const videoPlaying = ref({});
// 视频加载完成状态
const videoLoaded = ref({});
// 视频默认封面图
const videoPoster = ref("");

// 添加评论回复折叠状态
const expandedComments = ref({});

// 打赏相关
const showRewardDialog = ref(false);
const rewardContentVisible = ref(false);
const formattedRewardContent = ref("");

// 添加在线人数相关变量
const onlineCount = ref(0);
const wsConnection = ref(null);
const showOnlineChange = ref(false);
const onlineChangeText = ref("");

// 置顶相关变量
const showStickDialog = ref(false);

// 活跃度提示相关
const showTip = ref(false);
const tipPoints = ref(0);
const tipDescription = ref("");

// 添加标记是否是第一次收到在线人数增加的消息
const isFirstJoinMessage = ref(true);

// 判断当前用户是否为文章作者
const isCurrentUserAuthor = () => {
  try {
    if (!article.value) return false;

    const userInfo = uni.getStorageSync("userInfo");
    if (!userInfo) return false;

    const userInfoObj = JSON.parse(userInfo);
    if (!userInfoObj || !userInfoObj.oId) return false;

    return userInfoObj.oId == article.value.articleAuthorId;
  } catch (error) {
    console.error("判断作者身份出错:", error);
    return false;
  }
};

// 判断文章是否已置顶
const isArticleSticky = computed(() => {
  if (!article.value) return false;
  return (
    article.value.articleStick > 0 && article.value.articleStickRemains > 0
  );
});

// 切换评论排序方式
const toggleSortOrder = () => {
  isDescOrder.value = !isDescOrder.value;
  // 重新排序评论
  sortComments();
};

// 对评论进行排序
const sortComments = () => {
  if (comments.value.length === 0) return;

  // 复制一份评论列表进行排序
  const sortedComments = [...comments.value];

  // 根据排序方式对评论进行排序
  sortedComments.sort((a, b) => {
    const timeA = new Date(a.commentCreateTime);
    const timeB = new Date(b.commentCreateTime);

    return isDescOrder.value
      ? timeB - timeA // 倒序：最新的在前
      : timeA - timeB; // 正序：最早的在前
  });

  // 对每个评论中的回复也进行排序
  sortedComments.forEach((comment) => {
    if (comment.replies && comment.replies.length > 0) {
      comment.replies.sort((a, b) => {
        const timeA = new Date(a.commentCreateTime);
        const timeB = new Date(b.commentCreateTime);

        return isDescOrder.value
          ? timeB - timeA // 倒序：最新的在前
          : timeA - timeB; // 正序：最早的在前
      });
    }
  });

  // 更新评论列表
  comments.value = sortedComments;
};

// 获取评论作者名称
const getCommentAuthorName = (comment) => {
  if (!comment) return "";

  // 如果存在纯文本内容，添加提示
  const videoIndicator = comment.plainTextContent ? " [包含视频]" : "";

  return (
    (comment.commentAuthorNickName ||
      comment.commentAuthorName ||
      (comment.commenter
        ? comment.commenter.userNickname || comment.commenter.userName
        : "")) + videoIndicator
  );
};

// 切换标签页
const switchTab = (index) => {
  currentTab.value = index;
  // 如果切换到评论标签页，且还没有加载过评论，则加载评论
  if (index === 1 && comments.value.length === 0) {
    loadComments();
  }
};

// swiper滑动切换事件
const swiperChange = (e) => {
  currentTab.value = e.detail.current;
  // 如果滑动到评论标签页，且还没有加载过评论，则加载评论
  if (e.detail.current === 1 && comments.value.length === 0) {
    loadComments();
  }
};

// 滚动到底部
const onReachBottom = () => {
  if (currentTab.value === 1) {
    loadMoreComments();
  }
};

// 获取路由参数
const getRouteParams = () => {
  const pages = getCurrentPages();
  const currentPage = pages[pages.length - 1];
  const { id } = currentPage.$page.options;
  if (id) {
    articleId.value = id;
  } else {
    showError("参数错误");
    setTimeout(() => {
      uni.navigateBack();
    }, 1500);
  }
};
// 跳转到用户详情页
const navigateToUserDetail = (username) => {
  uni.navigateTo({
    url: `/pages/user/user-profile?username=${username}`,
  });
};
// 格式化时间显示
const formatTime = (timestamp) => {
  return timeAgo(timestamp);
};

// 格式化标签
const formatTags = (tagString) => {
  if (!tagString) return [];
  return tagString.split(",");
};

// 格式化文章内容的计算属性
const parsedContent = computed(() => {
  if (!article.value?.articleContent) return [];

  try {
    const content = article.value.articleContent;
    const nodes = [];

    // 使用正则表达式匹配视频标签，支持各种格式的视频标签
    const videoRegex = /<video[^>]*src=["']([^"']*)["'][^>]*>.*?<\/video>/g;
    let lastIndex = 0;
    let match;
    let videoIndex = 0;

    while ((match = videoRegex.exec(content)) !== null) {
      // 添加视频前的文本内容
      if (match.index > lastIndex) {
        nodes.push({
          type: "text",
          content: formatContent(content.substring(lastIndex, match.index)),
        });
      }

      // 提取视频路径和其他属性
      const videoSrc = match[1];

      // 为每个视频添加一个唯一标识
      const videoKey = `video-${Date.now()}-${nodes.length}`;

      // 尝试从视频标签中提取width和height属性
      const widthMatch = match[0].match(/width=["']([^"']*)["']/);
      const heightMatch = match[0].match(/height=["']([^"']*)["']/);

      // 添加视频节点
      nodes.push({
        type: "video",
        src: videoSrc,
        key: videoKey,
        index: videoIndex,
        width: widthMatch ? widthMatch[1] : "100%",
        height: heightMatch ? heightMatch[1] : "auto",
        original: match[0], // 保存原始的视频标签
      });

      // 为这个视频设置一个定时器，5秒后如果还没加载完成，自动标记为已加载
      const currentVideoIndex = videoIndex;
      setTimeout(() => {
        if (!videoLoaded.value[currentVideoIndex]) {
          console.log("视频加载超时，自动标记为已加载:", currentVideoIndex);
          videoLoaded.value[currentVideoIndex] = true;
        }
      }, 5000);

      videoIndex++;
      lastIndex = match.index + match[0].length;
    }

    // 添加最后一个视频后的文本内容
    if (lastIndex < content.length) {
      nodes.push({
        type: "text",
        content: formatContent(content.substring(lastIndex)),
      });
    }

    // 如果没有找到视频标签，则将整个内容作为文本内容
    if (nodes.length === 0) {
      nodes.push({
        type: "text",
        content: formatContent(content),
      });
    }

    // 记录视频数量用于调试
    console.log(
      "文章中找到视频数量:",
      nodes.filter((node) => node.type === "video").length
    );
    console.log(
      "视频节点信息:",
      nodes.filter((node) => node.type === "video")
    );

    return nodes;
  } catch (error) {
    console.error("解析内容出错：", error);
    // 出错时至少返回原始内容
    return [
      {
        type: "text",
        content: article.value.articleContent,
      },
    ];
  }
});

// 修改 formatContent 函数，优化图片标识和处理
const formatContent = (content) => {
  if (!content) return "";

  try {
    // 处理图片样式，添加class方便后续交互识别，同时保留原有样式
    content = content.replace(
      /<img/gi,
      '<img class="content-image" data-preview="true" style="max-width:100%;height:auto;display:block;border-radius:8rpx;"'
    );

    // 处理视频标签样式，但不替换，因为视频已经在parsedContent中单独处理
    // 这里只是为了防止formatContent被单独调用时能处理视频标签
    content = content.replace(
      /<video/gi,
      '<video class="content-video" style="max-width:100%;height:auto;display:block;border-radius:8rpx;" controls'
    );

    // 处理代码块样式
    content = content.replace(
      /<pre><code>/gi,
      '<pre class="code-block"><code>'
    );

    // 处理段落样式
    content = content.replace(/<p>/gi, '<p class="content-paragraph">');

    // 处理链接样式
    content = content.replace(/<a/gi, '<a class="content-link"');

    return content;
  } catch (error) {
    console.error("格式化内容出错：", error);
    return content;
  }
};

// 格式化评论内容的函数
const formattedCommentContent = (comment) => {
  if (!comment?.commentContent) return "";

  try {
    let content = comment.commentContent;

    // 检查是否包含视频标签
    const hasVideo = /<video[^>]*src=["'][^"']*["'][^>]*>.*?<\/video>/g.test(
      content
    );
    if (hasVideo) {
      // 为包含视频的评论添加标记
      comment.containsVideo = true;
    }

    // 处理图片样式，添加class方便后续交互识别
    content = content.replace(
      /<img/gi,
      '<img class="comment-image" data-preview="true" style="max-width:100%;height:auto;display:block;border-radius:8rpx;"'
    );

    // 处理视频标签样式
    content = content.replace(
      /<video/gi,
      '<video class="comment-video" style="max-width:100%;height:auto;display:block;border-radius:8rpx;margin:10rpx 0;" controls show-center-play-btn="true"'
    );

    // 处理代码块样式
    content = content.replace(
      /<pre><code>/gi,
      '<pre class="code-block"><code>'
    );

    // 处理段落样式
    content = content.replace(/<p>/gi, '<p class="content-paragraph">');

    // 处理链接样式
    content = content.replace(/<a/gi, '<a class="content-link"');

    return content;
  } catch (error) {
    console.error("格式化内容出错：", error);
    return content;
  }
};

// 处理文章内容点击事件，用于图片预览
const handleContentTap = (event) => {
  console.log("点击内容:", event);
  // 获取点击的元素
  const target = event.target;
  console.log("点击的元素:", target);

  // 检查是否点击了图片
  if (target && target.nodeName && target.nodeName.toLowerCase() === "img") {
    console.log("点击了图片元素");
    const imageUrl = target.src || target.getAttribute("src");
    if (imageUrl) {
      console.log("图片URL:", imageUrl);
      // 收集页面中所有图片并预览
      openImagePreview(imageUrl);
    }
  }

  // 检查是否点击了视频
  if (target && target.nodeName && target.nodeName.toLowerCase() === "video") {
    console.log("点击了视频元素");
    // 视频播放控制由浏览器原生控件处理
  }
};

// 打开图片预览
const openImagePreview = (url) => {
  previewImageUrl.value = url;
  showImagePreview.value = true;
};

// 关闭图片预览
const closeImagePreview = () => {
  showImagePreview.value = false;
};

// 提取图片并预览的辅助函数
const extractImagesAndPreview = (currentImageUrl, isCommentImage = false) => {
  try {
    // 根据点击的图片类型决定搜索范围
    const selector = isCommentImage ? ".comment-image" : ".content-image";
    const query = uni.createSelectorQuery();

    query
      .selectAll(selector)
      .boundingClientRect()
      .exec((res) => {
        if (res && res[0] && res[0].length > 0) {
          // 从选择器结果中提取src属性
          const allImages = res[0]
            .map((node) => {
              // 尝试从node的dataset中获取src
              return node.src || "";
            })
            .filter((src) => src); // 过滤掉空值

          // 如果没有找到其他图片，至少包含当前图片
          if (allImages.length === 0) {
            allImages.push(currentImageUrl);
          }

          // 使用预览方法
          if (allImages.length > 1) {
            // 如果有多张图片，使用uni.previewImage
            uni.previewImage({
              urls: allImages,
              current: currentImageUrl,
              indicator: "number",
              loop: true,
              fail: (err) => {
                console.error("多图预览失败，降级到单图预览:", err);
                // 降级到单图预览
                openImagePreview(currentImageUrl);
              },
            });
          } else {
            // 单张图片使用ImageViewer组件
            openImagePreview(currentImageUrl);
          }
        } else {
          // 如果没有找到图片，只预览当前点击的图片
          openImagePreview(currentImageUrl);
        }
      });
  } catch (error) {
    console.error("提取图片失败:", error);
    // 出错时至少尝试预览当前图片
    openImagePreview(currentImageUrl);
  }
};

// 加载文章详情
const loadArticleDetail = async () => {
  if (!articleId.value) return;

  try {
    showLoading("加载中");

    const res = await api.article.getArticleDetail(articleId.value);

    if (res.code === 0) {
      article.value = res.data.article;
      // 记录文章查看活跃度
      handleActivity("VIEW");

      // 检查是否已经打赏过或是否是作者本人
      if (
        (res.data.article.rewarded && res.data.article.articleRewardContent) ||
        res.data.article.articleAuthor.userName ===
          uni.getStorageSync("userName")
      ) {
        // 直接显示打赏内容
        formattedRewardContent.value = formatContent(
          res.data.article.articleRewardContent
        );
        rewardContentVisible.value = true;
      }

      // 获取优质评论
      if (res.data.article.articleNiceComments) {
        niceComments.value = res.data.article.articleNiceComments;
      }
      // 获取评论总页数
      if (res.data.pagination) {
        totalPages.value = res.data.pagination.paginationPageCount;
        // 设置当前页为最新一页
        commentPage.value = totalPages.value;
      }

      // 文章加载完成后，等待DOM渲染，然后刷新视频组件
      nextTick(() => {
        setTimeout(() => {
          refreshVideos();
          // 额外添加一个短时间后检查视频加载状态的操作
          setTimeout(() => {
            checkAllVideosLoaded();
          }, 2000);
        }, 500);
      });
    } else {
      showError(res.msg || "获取文章详情失败");
    }
  } catch (error) {
    showError(error.message || "获取文章详情失败");
  } finally {
    hideLoading();
  }
};

// 添加检查所有视频是否已加载的方法
const checkAllVideosLoaded = () => {
  // 查找所有视频元素
  const query = uni.createSelectorQuery();
  query.selectAll(".article-video").boundingClientRect();
  query.exec((res) => {
    if (res && res[0] && res[0].length > 0) {
      console.log("检查视频加载状态，找到视频数量:", res[0].length);

      // 遍历所有视频节点
      res[0].forEach((video, index) => {
        // 如果视频节点存在但未标记为已加载，则手动标记为已加载
        if (!videoLoaded.value[index]) {
          console.log("手动标记视频为已加载:", index);
          videoLoaded.value[index] = true;
        }
      });
    }
  });
};

// 加载评论
const loadComments = async () => {
  if (isLoadingComments.value) return;

  try {
    isLoadingComments.value = true;
    const res = await api.article.getArticleComments(
      articleId.value,
      commentPage.value
    );
    if (res.code === 0) {
      let commentList = res.data.articleComments;

      // 获取评论总页数(如果接口返回)
      if (res.data.pagination) {
        totalPages.value = res.data.pagination.paginationPageCount;
        // 确保commentPage不超过总页数
        if (commentPage.value > totalPages.value) {
          commentPage.value = totalPages.value;
        }
      }

      // 处理评论结构：主评论 + 所有回复平铺到一起
      const rootComments = [];
      const replyMap = {};

      // 先找出所有主评论
      commentList.forEach((comment) => {
        if (!comment.commentOriginalCommentId) {
          // 主评论
          comment.replies = [];
          rootComments.push(comment);
          // 创建回复映射，用于后面查找
          replyMap[comment.oId] = comment;
        }
      });

      // 处理所有回复，包括回复的回复
      commentList.forEach((comment) => {
        if (comment.commentOriginalCommentId) {
          // 查找这条回复对应的主评论
          let rootComment = findRootComment(comment, commentList, replyMap);
          if (rootComment) {
            // 将回复添加到主评论下
            rootComment.replies.push(comment);
          } else {
            // 如果找不到对应的主评论，作为单独的评论处理
            comment.replies = [];
            rootComments.push(comment);
          }
        }
      });

      // 排序
      rootComments.sort((a, b) => {
        const timeA = new Date(a.commentCreateTime);
        const timeB = new Date(b.commentCreateTime);
        return isDescOrder.value ? timeB - timeA : timeA - timeB;
      });

      // 对每个主评论的回复也进行排序
      rootComments.forEach((comment) => {
        if (comment.replies && comment.replies.length > 0) {
          comment.replies.sort((a, b) => {
            const timeA = new Date(a.commentCreateTime);
            const timeB = new Date(b.commentCreateTime);
            // 始终按时间顺序排序（早的在前，晚的在后）
            return timeA - timeB;
          });
        }
      });

      // 更新评论列表
      if (commentPage.value === totalPages.value) {
        comments.value = rootComments;
      } else {
        comments.value = [...comments.value, ...rootComments];
      }

      // 只要当前页不是第一页，就可以继续加载更多
      hasMoreComments.value = commentPage.value > 1;

      console.log(
        `评论加载成功: 当前第${commentPage.value}页，共${totalPages.value}页`
      );
      console.log(
        `本页评论数: ${rootComments.length}, 当前总评论数: ${comments.value.length}`
      );
    } else {
      showError(res.msg || "获取评论失败");
    }
  } catch (error) {
    showError(error.message || "获取评论失败");
  } finally {
    isLoadingComments.value = false;
  }
};

// 递归查找回复所属的主评论
const findRootComment = (reply, commentList, replyMap) => {
  if (!reply.commentOriginalCommentId) {
    return reply; // 本身就是主评论
  }

  // 优先尝试从映射中直接获取主评论
  if (replyMap[reply.commentOriginalCommentId]) {
    return replyMap[reply.commentOriginalCommentId];
  }

  // 如果找不到，可能回复的是另一条回复，需要递归向上查找
  const parent = commentList.find(
    (c) => c.oId === reply.commentOriginalCommentId
  );
  if (!parent) {
    return null; // 找不到父评论
  }

  // 递归查找根评论
  return findRootComment(parent, commentList, replyMap);
};

// 加载更多评论
const loadMoreComments = async () => {
  // 只要还有上一页并且不在加载中，就可以加载更多
  if (commentPage.value <= 1 || isLoadingComments.value) return;
  commentPage.value--;
  await loadComments();
};

// 显示评论输入框
const showCommentInput = () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }
  showCommentBox.value = true;
  nextTick(() => {
    commentFocus.value = true;
  });
};

// 隐藏评论输入框
const hideCommentInput = () => {
  showCommentBox.value = false;
  commentContent.value = "";
  replyToComment.value = null;
  keyboardHeight.value = 0;
};

// 回复评论
const handleReplyComment = (comment) => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  // 如果评论内容包含视频标签，提取纯文本以便更好地显示在回复框中
  if (comment.commentContent && comment.commentContent.includes("<video")) {
    // 创建临时元素解析HTML
    const tempDiv = document.createElement("div");
    tempDiv.innerHTML = comment.commentContent;
    // 移除视频标签，只保留文本内容
    const videoTags = tempDiv.getElementsByTagName("video");
    while (videoTags.length > 0) {
      const videoTag = videoTags[0];
      const textNode = document.createTextNode("[视频]");
      videoTag.parentNode.replaceChild(textNode, videoTag);
    }
    // 更新评论对象的一个临时属性，用于显示
    comment.plainTextContent = tempDiv.textContent || tempDiv.innerText;
  }

  replyToComment.value = comment;
  showCommentBox.value = true;
  commentContent.value = "";

  nextTick(() => {
    commentFocus.value = true;
  });
};

// 提交评论
const submitComment = async () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  if (!commentContent.value.trim()) {
    showError("评论内容不能为空");
    return;
  }

  try {
    submitting.value = true;
    const params = {
      commentContent: commentContent.value,
      commentOriginalCommentId: replyToComment.value
        ? replyToComment.value.oId
        : "",
    };

    const res = await api.article.addReplyComment(
      articleId.value,
      commentContent.value,
      replyToComment.value ? replyToComment.value.oId : ""
    );

    if (res.code === 0) {
      // 记录评论活跃度
      handleActivity("COMMENT");
      article.value.articleCommentCount++;
      commentContent.value = "";
      hideCommentInput();
      loadComments();
      currentTab.value = 1;
    } else {
      showError(res.msg || "评论失败");
    }
  } catch (error) {
    showError(error.message || "评论失败");
  } finally {
    submitting.value = false;
    hideLoading();
  }
};
// 处理点赞评论
const handleLikeComment = async (comment) => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }
  const res = await api.article.likeComment(comment.oId);
  if (res.code === 0) {
    if (res.type === -1) {
      // 更新评论的点赞状态
      comment.hasLiked = true;
      if (comment) {
        comment.commentGoodCnt++;
      }
    } else {
      // 更新评论的点赞状态
      comment.hasLiked = false;
      if (comment) {
        comment.commentGoodCnt--;
      }
    }
  } else {
    showError(res.msg || "点赞失败");
  }
};

// 处理感谢评论
const handleThankComment = async (comment) => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  // 检查是否是自己的评论
  if (
    comment.commenter &&
    comment.commenter.userName === uni.getStorageSync("userName")
  ) {
    showError("不能感谢自己的评论");
    return;
  }

  thankTargetType.value = "comment";
  thankTargetId.value = comment.oId;
  showThankConfirm.value = true;
};

// 处理点赞按钮点击
const handleLike = async () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  if (hasLiked.value) {
    showError("您已经点赞过了");
    return;
  }
  try {
    const res = await api.article.likeArticle(articleId.value);

    if (res.code === 0) {
      if (res.type === -1) {
        hasLiked.value = true;
        if (article.value) {
          article.value.articleGoodCnt++;
        }
        // 记录点赞活跃度
        handleActivity("VOTE");
      } else {
        hasLiked.value = false;
        if (article.value) {
          article.value.articleGoodCnt--;
        }
      }
    } else {
      showError(res.msg || "点赞失败");
    }
  } catch (error) {
    showError(error.message || "点赞失败");
  } finally {
    hideLoading();
  }
};

// 跳转到登录页
const goToLogin = () => {
  showLoginTip.value = false;
  uni.navigateTo({
    url: "/pages/login/login",
  });
};

// 键盘高度变化事件
const onFocus = (e) => {
  // #ifdef APP-PLUS
  keyboardHeight.value = e.detail.height || 0;
  // #endif
};

const onBlur = () => {
  keyboardHeight.value = 0;
};

// 监听键盘高度变化
// #ifdef APP-PLUS
uni.onKeyboardHeightChange((res) => {
  if (res.height === 0) {
    // 键盘收起时，强制失焦并重置位置
    keyboardHeight.value = 0;
    commentFocus.value = false;
    setTimeout(() => {
      scrollToBottom(300);
    }, 300);
  } else {
    keyboardHeight.value = res.height;
  }
});
// #endif
// 优化的滚动到底部函数
const scrollToBottom = (delay = 100) => {
  setTimeout(() => {
    try {
      // 创建选择器查询
      const query = uni.createSelectorQuery().in(this);
      query.select("#chat-scroll").boundingClientRect();
      query.select(".chat-list").boundingClientRect();

      query.exec((res) => {
        if (res && res[0] && res[1]) {
          const scrollHeight = res[1].height;
          const viewHeight = res[0].height;

          // 计算需要滚动的位置，添加一点额外空间确保完全滚动到底部
          const newScrollTop = scrollHeight - viewHeight + 100;

          if (newScrollTop > 0) {
            // 直接设置滚动位置，不使用动画
            scrollTop.value = newScrollTop;

            // 延迟后再次检查并滚动，确保完全滚动到底部
            setTimeout(() => {
              query.exec((res) => {
                if (res && res[0] && res[1]) {
                  const finalScrollHeight = res[1].height;
                  const finalViewHeight = res[0].height;
                  const finalScrollTop =
                    finalScrollHeight - finalViewHeight + 100;

                  // 如果最终滚动位置大于当前滚动位置，则再次滚动
                  if (finalScrollTop > scrollTop.value) {
                    scrollTop.value = finalScrollTop;
                  }
                }
              });
            }, 100);
          }
        } else {
          // 备用方案：设置一个很大的值
          scrollTop.value = 999999;
        }
      });
    } catch (error) {
      console.error("滚动到底部失败:", error);
      // 备用方案
      scrollTop.value = 999999;
    }
  }, delay);
};
// 组件卸载时移除监听
onUnmounted(() => {
  // #ifdef APP-PLUS
  uni.offKeyboardHeightChange();
  // #endif
});

// 计算并设置内容区域高度
const calculateContentHeight = () => {
  const windowHeight = uni.getSystemInfoSync().windowHeight;
  const tabBarHeight = 80; // 顶部标签栏高度（rpx）
  const footerHeight = 90; // 底部操作栏高度（rpx）

  // 转换rpx为px
  const tabBarHeightPx = uni.upx2px(tabBarHeight);
  const footerHeightPx = uni.upx2px(footerHeight);

  // 设置内容区域高度
  contentHeight.value = windowHeight - tabBarHeightPx - footerHeightPx;
};

// 重写swiper高度计算方法
const calculateSwiperHeight = () => {
  calculateContentHeight();
};

// 返回上一页
const goBack = () => {
  uni.navigateBack({
    delta: 1,
  });
};

// 处理感谢文章
const handleThank = async () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  if (hasThanked.value) {
    showError("您已经感谢过了");
    return;
  }

  // 检查是否是自己的文章
  if (
    article.value &&
    article.value.articleAuthor.userName === uni.getStorageSync("userName")
  ) {
    showError("不能感谢自己的文章");
    return;
  }

  thankTargetType.value = "article";
  thankTargetId.value = articleId.value;
  showThankConfirm.value = true;
};

// 显示置顶确认对话框或显示剩余时间
const showStickConfirm = () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  // 判断是否已经置顶
  if (isArticleSticky.value) {
    // 已经置顶，显示剩余时间弹窗
    const remainMinutes = article.value.articleStickRemains;
    uni.showModal({
      title: "置顶中",
      content: `您的帖子正在置顶中\n剩余时间 ${remainMinutes} 分钟`,
      showCancel: false,
      confirmText: "知道了",
    });
  } else {
    // 未置顶，显示确认消费弹窗
    showStickDialog.value = true;
  }
};

// 确认置顶
const confirmStick = async () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  try {
    showLoading("处理中");
    const res = await api.article.stickArticle(articleId.value);

    if (res.code === 0) {
      showSuccess(res.msg);
    } else {
      showError(res.msg || "操作失败");
    }
  } catch (error) {
    showError(error.message || "操作失败");
  } finally {
    hideLoading();
    showStickDialog.value = false;
  }
};

// 处理图片上传
const handleImageUpload = () => {
  chooseAndUploadImage({
    count: 1,
    loadingText: "图片上传中...",
    successText: "图片上传成功",
  })
    .then((imageUrl) => {
      // 使用img标签添加到评论内容
      commentContent.value += `<img src="${imageUrl}" alt="图片" style="max-width:100%;height:auto;" />`;
      // 如果内容不为空则自动提交
      if (commentContent.value.trim()) {
        submitComment();
      }
    })
    .catch((error) => {
      console.error("上传图片失败:", error);
    });
};

// 加载表情包
const loadEmoticons = async () => {
  if (isLoadingEmoticons.value) return;

  try {
    isLoadingEmoticons.value = true;
    // 加载默认表情
    const defaultRes = await api.chat.getDefaultEmoticon();
    if (defaultRes.code === 0) {
      // 处理新的数据格式
      if (Array.isArray(defaultRes.data)) {
        // 将数据转换为所需格式: [{key: value}, ...] => [{key, value}, ...]
        defaultEmoticons.value = defaultRes.data.map((item) => {
          const key = Object.keys(item)[0];
          return {
            key: key,
            value: item[key],
          };
        });
      } else {
        defaultEmoticons.value = [];
      }
    }

    // 加载用户表情包
    const customRes = await api.chat.getEmoticon();
    if (customRes.code === 0) {
      if (Array.isArray(customRes.data)) {
        customEmoticons.value = customRes.data;
      } else {
        try {
          const parsedData = JSON.parse(customRes.data);
          if (Array.isArray(parsedData)) {
            customEmoticons.value = parsedData;
          }
        } catch (e) {
          console.error("解析表情包数据失败", e);
        }
      }
    }
  } catch (error) {
    console.error("加载表情包失败", error);
  } finally {
    isLoadingEmoticons.value = false;
  }
};

// 处理表情选择
const handleEmoji = () => {
  if (!showEmojiPanel.value) {
    loadEmoticons();
  }
  showEmojiPanel.value = !showEmojiPanel.value;
};

// 选择表情并发送
const selectEmoji = async (emoji) => {
  // 判断emoji是否为表情文本还是图片URL
  if (typeof emoji === "string" && emoji.startsWith("http")) {
    // 如果是图片URL，使用img标签
    commentContent.value += `<img src="${emoji}" alt="表情" style="max-width:100px;height:auto;" />`;
  } else {
    // 如果是文本表情，直接添加
    commentContent.value += emoji;
  }

  // 关闭表情面板
  showEmojiPanel.value = false;
};

// 确认感谢
const confirmThank = async () => {
  try {
    let res;
    if (thankTargetType.value === "article") {
      res = await api.article.thankArticle(thankTargetId.value);
      if (res.code === 0) {
        hasThanked.value = true;
        if (article.value) {
          article.value.articleThankCnt++;
        }
        // 记录感谢文章活跃度
        handleActivity("THANK");
      }
    } else {
      res = await api.article.thankComment(thankTargetId.value);
      if (res.code === 0) {
        // 记录感谢评论活跃度
        handleActivity("THANK_COMMENT");
      }
    }
  } catch (error) {
    showError(error.message || "感谢失败");
  } finally {
    showThankConfirm.value = false;
  }
};

// 关闭图片查看器
const closeImageViewer = () => {
  showImageViewer.value = false;
};

// 切换图片
const switchImage = (index) => {
  currentImageIndex.value = index;
};

// 更新图片预览方法，使用ImageViewer组件
const previewImage = (urls, current) => {
  if (!urls || !Array.isArray(urls) || urls.length === 0) {
    console.error("图片URL格式不正确");
    return;
  }

  // 使用ImageViewer组件预览
  previewImageUrl.value = current || urls[0];
  showImagePreview.value = true;
};

// 在script部分添加两个函数来判断是否是最多点赞和最多感谢的评论
const isTopLiked = (comment) => {
  if (!comments.value || comments.value.length === 0) return false;

  // 找出点赞数最多的评论
  const maxLikes = Math.max(
    ...comments.value.map((c) => c.commentGoodCnt || 0)
  );
  // 点赞数需要大于0且等于最大点赞数
  return maxLikes > 0 && (comment.commentGoodCnt || 0) === maxLikes;
};

const isTopThanked = (comment) => {
  if (!comments.value || comments.value.length === 0) return false;

  // 找出感谢数最多的评论
  const maxThanks = Math.max(
    ...comments.value.map((c) => c.commentThankCnt || 0)
  );
  // 感谢数需要大于0且等于最大感谢数
  return maxThanks > 0 && (comment.commentThankCnt || 0) === maxThanks;
};

// 在script部分添加两个函数来判断是否是优质评论中最多点赞和最多感谢的评论
const isTopLikedInNice = (comment) => {
  if (!niceComments.value || niceComments.value.length === 0) return false;
  const likes = niceComments.value.map((c) => c.commentGoodCnt || 0);
  if (new Set(likes).size === 1) return false;
  const maxLikes = Math.max(...likes);
  return (comment.commentGoodCnt || 0) === maxLikes && maxLikes > 0;
};

const isTopThankedInNice = (comment) => {
  if (!niceComments.value || niceComments.value.length === 0) return false;
  const thanks = niceComments.value.map((c) => c.commentThankCnt || 0);
  if (new Set(thanks).size === 1) return false;
  const maxThanks = Math.max(...thanks);
  return (comment.commentThankCnt || 0) === maxThanks && maxThanks > 0;
};

onMounted(() => {
  // 注册全局预览方法
  uni.$previewImage = previewImage;

  getRouteParams();
  loadArticleDetail();
  calculateContentHeight();

  // 设置评论初始页为最后一页(即第一页最新评论)
  commentPage.value = totalPages.value || 1;

  // 使用uni-app的API监听窗口大小变化
  uni.onWindowResize((res) => {
    calculateContentHeight();
  });

  // 添加页面显示时的处理，用于刷新视频组件
  uni.$on("page-show", () => {
    setTimeout(() => {
      refreshVideos();
    }, 300);
  });

  // 获取文章在线人数
  loadArticleOnlineCount();

  // 连接WebSocket
  connectWebSocket();
});

// 页面显示时刷新视频
onActivated(() => {
  setTimeout(() => {
    refreshVideos();
  }, 300);
});

// 刷新视频组件的方法
const refreshVideos = () => {
  if (!article.value?.articleContent) return;

  try {
    // 重置视频相关状态
    videoLoaded.value = {};
    videoPlaying.value = {};
    videoLoadError.value = {};

    // 生成默认的视频封面
    try {
      // 尝试从文章内容中找到第一张图片作为视频封面
      const imgRegex = /<img[^>]*src=["']([^"']*)["'][^>]*>/i;
      const imgMatch = article.value.articleContent.match(imgRegex);
      if (imgMatch && imgMatch[1]) {
        videoPoster.value = imgMatch[1];
      } else {
        // 如果没有图片，使用默认封面
        videoPoster.value = "/static/video-poster.png";
      }
    } catch (e) {
      console.error("生成视频封面失败", e);
      videoPoster.value = "/static/video-poster.png";
    }

    // 在下一个UI渲染周期后执行
    nextTick(() => {
      // 查找所有视频组件
      const query = uni.createSelectorQuery();
      query.selectAll(".article-video").boundingClientRect();
      query.exec((res) => {
        if (res && res[0] && res[0].length > 0) {
          console.log("找到视频组件数量:", res[0].length);
          // 为每个视频组件设置高度和宽度以确保正确显示
          res[0].forEach((video, index) => {
            const videoId = `video-${index}`;
            const videoContext = uni.createVideoContext(videoId);
            if (videoContext) {
              // 刷新视频上下文
              videoContext.stop();
              setTimeout(() => {
                videoContext.seek(0);
              }, 100);
            }
          });
        } else {
          console.log("未找到视频组件");
        }
      });
    });
  } catch (error) {
    console.error("刷新视频组件出错:", error);
  }
};

onUnmounted(() => {
  // 移除全局方法
  delete uni.$previewImage;

  // 移除页面显示事件监听
  uni.$off("page-show");

  // 移除窗口大小变化监听
  uni.offWindowResize((res) => {
    calculateContentHeight();
  });

  // 关闭WebSocket连接
  closeWebSocket();
});

// 切换表情标签
const switchEmojiTab = (index) => {
  emojiTabIndex.value = index;
};

// 表情面板滑动切换事件
const onEmojiTabChange = (e) => {
  emojiTabIndex.value = e.detail.current;
};

// 在script部分添加处理视频错误和播放的函数
const handleVideoError = (e) => {
  console.error("视频播放错误:", e);
  const index = e.currentTarget.id.replace("video-", "");
  // 设置视频加载错误状态
  videoLoadError.value[index] = true;
  // 重置播放状态
  videoPlaying.value[index] = false;
};

const handleVideoPlay = (e) => {
  console.log("视频开始播放:", e);
  const index = e.currentTarget.id.replace("video-", "");
  // 清除视频错误状态
  videoLoadError.value[index] = false;
  // 设置播放状态
  videoPlaying.value[index] = true;

  // 监听视频退出全屏事件
  const videoContext = uni.createVideoContext("video-" + index);
  if (videoContext) {
    // 部分平台支持exitFullScreen事件
    // #ifdef APP-PLUS
    videoContext.onFullscreenChange((e) => {
      if (!e.fullScreen) {
        videoPlaying.value[index] = false;
        videoContext.pause();
      }
    });
    // #endif
  }
};

// 处理视频加载完成
const handleVideoLoaded = (e, index) => {
  console.log("视频元数据加载完成:", e, index);
  // 设置视频加载完成状态
  videoLoaded.value[index] = true;
};

// 播放视频方法
const playVideo = (videoId) => {
  try {
    const videoIndex = videoId.replace("video-", "");
    const videoContext = uni.createVideoContext(videoId);
    if (videoContext) {
      // 标记为正在播放
      videoPlaying.value[videoIndex] = true;

      // 确保视频已加载
      if (!videoLoaded.value[videoIndex]) {
        videoLoaded.value[videoIndex] = true;
      }

      // H5环境下不支持直接全屏，需要先播放
      // #ifdef H5
      videoContext.play();
      setTimeout(() => {
        videoContext.requestFullScreen();
      }, 300);
      // #endif

      // 非H5环境可以直接全屏播放
      // #ifndef H5
      videoContext.requestFullScreen({ direction: 0 });
      setTimeout(() => {
        videoContext.play();
      }, 200);
      // #endif
    } else {
      console.error("获取视频上下文失败", videoId);
    }
  } catch (error) {
    console.error("播放视频失败:", error);
  }
};

// 添加重试加载视频的方法
const retryLoadVideo = (index) => {
  console.log("重试加载视频:", index);
  // 重置错误状态
  videoLoadError.value[index] = false;
  // 重置加载状态，触发重新加载
  videoLoaded.value[index] = false;

  // 获取视频上下文并重新加载
  const videoContext = uni.createVideoContext("video-" + index);
  if (videoContext) {
    videoContext.stop();
    setTimeout(() => {
      videoContext.play();
    }, 300);
  }

  // 如果5秒后仍未加载成功，再次标记为已加载
  setTimeout(() => {
    if (!videoLoaded.value[index]) {
      videoLoaded.value[index] = true;
    }
  }, 5000);
};

// 强制播放视频
const forcePlayVideo = (index) => {
  console.log("强制播放视频:", index);
  videoLoaded.value[index] = true;
  setTimeout(() => {
    playVideo("video-" + index);
  }, 100);
};

// 显示打赏确认弹窗
const showRewardConfirm = () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  // 检查是否是自己的文章
  if (
    article.value &&
    article.value.articleAuthor.userName === uni.getStorageSync("userName")
  ) {
    showSuccess("这是您自己的文章，无需打赏");
    // 自己的文章直接显示打赏内容
    formattedRewardContent.value = formatContent(
      article.value.articleRewardContent
    );
    rewardContentVisible.value = true;
    return;
  }

  // 如果已经打赏过，直接显示内容
  if (article.value && article.value.rewarded) {
    formattedRewardContent.value = formatContent(
      article.value.articleRewardContent
    );
    rewardContentVisible.value = true;
    return;
  }

  showRewardDialog.value = true;
};

// 确认打赏
const confirmReward = async () => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  try {
    showLoading("处理中");
    const res = await api.article.rewardArticle(articleId.value);

    if (res.code === 0) {
      showRewardDialog.value = false;
      // 记录打赏活跃度
      handleActivity("REWARD");

      // 更新打赏数量
      if (article.value) {
        article.value.rewardedCnt = (article.value.rewardedCnt || 0) + 1;
      }

      // 显示打赏内容
      if (res.articleRewardContent) {
        formattedRewardContent.value = formatContent(res.articleRewardContent);
        rewardContentVisible.value = true;
      }
    } else {
      showError(res.msg || "打赏失败");
    }
  } catch (error) {
    showError(error.message || "打赏失败");
  } finally {
    hideLoading();
  }
};

// 加载打赏内容 - 只在需要时使用
const loadRewardContent = async () => {
  // 如果已经加载了打赏内容，就不再请求
  if (
    article.value &&
    article.value.articleRewardContent &&
    article.value.rewarded
  ) {
    formattedRewardContent.value = formatContent(
      article.value.articleRewardContent
    );
    rewardContentVisible.value = true;
    return;
  }

  try {
    const res = await api.article.rewardArticle(articleId.value);

    if (res.code === 0 && res.articleRewardContent) {
      formattedRewardContent.value = formatContent(res.articleRewardContent);
      rewardContentVisible.value = true;
    }
  } catch (error) {
    console.error("获取打赏内容失败", error);
  }
};

// 在 methods 中添加判断方法
const isMostLikedComment = (comment) => {
  if (!comments.value || comments.value.length === 0) return false;
  const likes = comments.value.map((c) => c.commentGoodCnt || 0);
  // 如果所有评论的点赞数都一样，就不显示标签
  if (new Set(likes).size === 1) return false;
  const maxLikes = Math.max(...likes);
  const result = (comment.commentGoodCnt || 0) === maxLikes && maxLikes > 0;
  return result;
};

const isMostThankedComment = (comment) => {
  if (!comments.value || comments.value.length === 0) return false;
  const thanks = comments.value.map((c) => c.commentThankCnt || 0);
  // 如果所有评论的感谢数都一样，就不显示标签
  if (new Set(thanks).size === 1) return false;
  const maxThanks = Math.max(...thanks);
  const result = (comment.commentThankCnt || 0) === maxThanks && maxThanks > 0;
  return result;
};

// 在script部分添加判断回复中最多点赞和最多感谢评论的函数
const isTopLikedReply = (reply, comment) => {
  if (!comment.replies || comment.replies.length === 0) return false;
  const likes = comment.replies.map((r) => r.commentGoodCnt || 0);
  if (new Set(likes).size === 1) return false;
  const maxLikes = Math.max(...likes);
  return (reply.commentGoodCnt || 0) === maxLikes && maxLikes > 0;
};

const isTopThankedReply = (reply, comment) => {
  if (!comment.replies || comment.replies.length === 0) return false;
  const thanks = comment.replies.map((r) => r.commentThankCnt || 0);
  if (new Set(thanks).size === 1) return false;
  const maxThanks = Math.max(...thanks);
  return (reply.commentThankCnt || 0) === maxThanks && maxThanks > 0;
};

// 优化获取回复目标名称的函数
const getReplyTargetName = (reply, comment) => {
  // 如果回复的是主评论
  if (reply.commentOriginalCommentId === comment.oId) {
    return (
      comment.commentAuthorNickName ||
      comment.commentAuthorName ||
      (comment.commenter
        ? comment.commenter.userNickname || comment.commenter.userName
        : "")
    );
  }

  // 如果回复的是其他回复
  for (const r of comment.replies) {
    if (r.oId === reply.commentOriginalCommentId) {
      return (
        r.commentAuthorNickName ||
        r.commentAuthorName ||
        (r.commenter ? r.commenter.userNickname || r.commenter.userName : "")
      );
    }
  }

  // 如果在当前评论的回复中找不到目标，可能在其他评论中
  for (const c of comments.value) {
    // 检查主评论
    if (c.oId === reply.commentOriginalCommentId) {
      return (
        c.commentAuthorNickName ||
        c.commentAuthorName ||
        (c.commenter ? c.commenter.userNickname || c.commenter.userName : "")
      );
    }

    // 检查回复
    if (c.replies) {
      for (const r of c.replies) {
        if (r.oId === reply.commentOriginalCommentId) {
          return (
            r.commentAuthorNickName ||
            r.commentAuthorName ||
            (r.commenter
              ? r.commenter.userNickname || r.commenter.userName
              : "")
          );
        }
      }
    }
  }

  return "用户"; // 找不到对应用户，返回默认值
};

// 获取文章在线人数
const loadArticleOnlineCount = async () => {
  if (!articleId.value) return;

  try {
    const res = await api.article.getArticleOnline(articleId.value);
    onlineCount.value = res.articleHeat || 0;
  } catch (error) {
    console.error("获取文章在线人数失败:", error);
  }
};

// 连接WebSocket
const connectWebSocket = () => {
  if (!articleId.value) return;

  try {
    // 检查登录状态
    const apiKey = getApiKey();
    if (!isLoggedIn() || !apiKey) {
      console.log("未登录，不建立WebSocket连接");
      return;
    }

    // 构建WebSocket URL 并直接在URL中添加参数
    const url = `wss://fishpi.cn/article-channel?apiKey=${apiKey}&articleId=${articleId.value}&articleType=article`;

    wsConnection.value = uni.connectSocket({
      url: url,
      success: () => {
        console.log("WebSocket连接成功");
      },
      fail: (err) => {
        console.error("WebSocket连接失败:", err);
      },
    });

    uni.onSocketOpen(() => {
      console.log("WebSocket已打开");
    });

    uni.onSocketError((err) => {
      console.error("WebSocket错误:", err);
    });

    uni.onSocketMessage((res) => {
      try {
        const data = JSON.parse(res.data);
        console.log("接收到WebSocket消息:", data);
        if (data.articleId === articleId.value && data.type === "articleHeat") {
          // 增加或减少在线人数
          if (data.operation === "+") {
            onlineCount.value++;
            // 只有不是第一条加入消息时才显示提示
            if (!isFirstJoinMessage.value) {
              showOnlineChangeNotification("有新朋友加入了阅读");
            } else {
              // 标记第一条消息已处理
              isFirstJoinMessage.value = false;
            }
          } else if (data.operation === "-") {
            if (onlineCount.value > 0) {
              onlineCount.value--;
              // 用户离开时仍可以显示提示
              showOnlineChangeNotification("有朋友离开了");
            }
          }
        }
      } catch (error) {
        console.error("解析WebSocket消息失败:", error);
      }
    });

    uni.onSocketClose(() => {
      console.log("WebSocket已关闭");
      wsConnection.value = null;
    });
  } catch (error) {
    console.error("WebSocket处理失败:", error);
  }
};

// 关闭WebSocket连接
const closeWebSocket = () => {
  if (wsConnection.value) {
    try {
      uni.closeSocket({
        success: () => {
          console.log("WebSocket已关闭");
        },
      });
    } catch (error) {
      console.error("关闭WebSocket失败:", error);
    }
  }
};

// 处理展开/折叠评论回复
const toggleReplies = (commentId) => {
  expandedComments.value[commentId] = !expandedComments.value[commentId];
};

// 判断评论回复是否展开
const isExpanded = (commentId) => {
  return !!expandedComments.value[commentId];
};

// 获取评论的可见回复
const getVisibleReplies = (comment) => {
  if (!comment.replies || comment.replies.length === 0) return [];

  // 如果展开了，返回所有回复
  if (isExpanded(comment.oId)) {
    return comment.replies;
  }

  // 如果没有展开，只返回前2条回复
  return comment.replies.slice(0, 2);
};

// 跳转到标签对应的文章列表页
const navigateToTagArticles = (tag) => {
  // 使用tagURI和tagTitle
  const tagURI = tag.tagURI;
  const tagName = encodeURIComponent(tag.tagTitle);
  uni.navigateTo({
    url: `/pages/article/tag-articles?uri=${tagURI}&name=${tagName}`,
  });
};

// 显示活跃度提示的方法
const showActivityTip = (points, description) => {
  tipPoints.value = points;
  tipDescription.value = description;
  showTip.value = true;

  // 2秒后自动隐藏
  setTimeout(() => {
    showTip.value = false;
  }, 2000);
};

// 处理活跃度记录
const handleActivity = (actionType) => {
  const result = activityManager.recordAction(actionType);
  if (result.success) {
    showActivityTip(result.points, result.description);
  }
};

// 添加在线人数变化提示方法
const showOnlineChangeNotification = (text) => {
  onlineChangeText.value = text;
  showOnlineChange.value = true;

  setTimeout(() => {
    showOnlineChange.value = false;
  }, 3000);
};

// 修改评论点击处理方法，添加直接回复功能
const handleCommentClick = (comment) => {
  if (!isLoggedIn()) {
    showLoginTip.value = true;
    return;
  }

  handleReplyComment(comment);
};

// 添加判断是否是文章作者的方法
const isArticleAuthor = (userName) => {
  if (!article.value || !userName) return false;
  return userName === article.value.articleAuthor.userName;
};
</script>

<style>
.container {
  display: flex;
  flex-direction: column;
  background-color: #f6f7f9;
}

.tab-bar {
  display: flex;
  height: 80rpx;
  background-color: #fff;
  border-bottom: 1rpx solid #f0f0f0;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  justify-content: center;
  align-items: center;
  padding-top: 30px;
}

.back-btn {
  position: absolute;
  left: 30rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 60rpx;
  height: 60rpx;
  z-index: 101;
}

.tab-wrapper {
  display: flex;
  width: 40%;
  margin: 0 auto;
}

.tab-item {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 30rpx;
  color: #666;
  position: relative;
}

.tab-item.active {
  color: #000000;
  font-weight: bold;
}

.tab-item.active:after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 35px;
  right: 0;
  height: 6rpx;
  background-color: #ffffff;
  border-radius: 3rpx;
  width: 20%;
  top: 26px;
}

.tab-placeholder {
  height: 80rpx;
}

.content-swiper {
  width: 100%;
}

.article-scroll,
.comment-scroll {
  width: 100%;
}

.article-detail {
  background-color: #fff;
  padding: 30rpx;
  margin-bottom: 16rpx;
  padding-bottom: 120rpx;
}

.article-header {
  margin-bottom: 30rpx;
}

.article-title {
  font-size: 42rpx;
  font-weight: 600;
  color: #333;
  line-height: 1.4;
  margin-bottom: 30rpx;
}

.article-meta {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-top: 24rpx;
  margin-bottom: 24rpx;
}

.author-info {
  display: flex;
  align-items: flex-start;
  flex: 1;
  min-width: 0;
}

.author-avatar {
  width: 72rpx;
  height: 72rpx;
  border-radius: 50%;
  margin-right: 16rpx;
  border: 1px solid #f0f0f0;
  flex-shrink: 0;
}

.author-detail {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

.author-name {
  font-size: 28rpx;
  color: #333;
  font-weight: 500;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 200rpx;
}

.publish-time {
  font-size: 24rpx;
  color: #999;
  margin-top: 6rpx;
}

.article-stats {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: center;
  gap: 8rpx;
}

.stat-item {
  display: flex;
  align-items: center;
  white-space: nowrap;
}

.stat-count {
  font-size: 24rpx;
  color: #999;
  margin-left: 6rpx;
}

.article-view-count {
  display: flex;
  align-items: center;
}

.view-count {
  font-size: 24rpx;
  color: #999;
  margin-left: 8rpx;
}

.article-online-count {
  display: flex;
  align-items: center;
  margin-bottom: 6rpx;
  transition: all 0.3s ease;
  padding: 4rpx 12rpx;
  border-radius: 30rpx;

  &.pulse {
    background-color: rgba(76, 175, 80, 0.1);
    transform: scale(1.05);
  }
}

.online-count {
  font-size: 24rpx;
  color: #999;
  margin-left: 8rpx;
  transition: color 0.3s ease;

  .pulse & {
    color: #4caf50;
  }
}

.tags-scroll {
  white-space: nowrap;
}

.article-tags {
  display: inline-flex;
  padding: 8rpx 0;
}

.tag {
  display: inline-block;
  font-size: 22rpx;
  color: #ff9800;
  background-color: rgba(255, 152, 0, 0.1);
  padding: 4rpx 12rpx;
  border-radius: 6rpx;
  margin-right: 10rpx;
}

.article-content {
  font-size: 30rpx;
  color: #333;
  line-height: 1.8;
}

.article-content video {
  width: 100%;
  height: auto;
  border-radius: 8rpx;
  margin: 20rpx 0;
}

.content-paragraph {
  margin: 20rpx 0;
  word-break: break-all;
  word-wrap: break-word;
}

.content-link {
  color: #0072ff;
  text-decoration: none;
  word-break: break-all;
  word-wrap: break-word;
}

/* 文章页面的评论区域样式 */
.article-comments {
  margin-top: 40rpx;
  padding-top: 20rpx;
  border-top: 16rpx solid #f6f7f9;
}

.article-comments .section-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 24rpx;
}

.article-comments .section-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
}

.article-comments .view-all {
  font-size: 26rpx;
  color: #0072ff;
}

.article-comments .empty-comment {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 40rpx 0;
  color: #999;
  font-size: 26rpx;
}

/* 评论区域样式 */
.comment-section {
  background-color: #fff;
  padding: 30rpx;
  padding-bottom: 120rpx;
}

.comment-section .section-header {
  margin-bottom: 30rpx;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 16rpx;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-left: 0;
  padding-right: 0;
}

.comment-section .section-title {
  font-size: 34rpx;
  font-weight: 600;
  color: #333;
}

.comment-list {
  margin-bottom: 20rpx;
}

/* 评论项通用样式 */
.comment-item {
  margin-bottom: 30rpx;
}

.comment-item:last-child {
  margin-bottom: 0;
}

.comment-body {
  flex: 1;
}

.comment-header {
  display: flex;
  align-items: flex-start;
  margin-bottom: -16rpx;
}

/* 预览评论中的头像 */
.preview-comment .commenter-avatar {
  width: 64rpx;
  height: 64rpx;
}
.reply-text {
  margin-left: 16rpx;
}
.commenter-avatar {
  width: 64rpx;
  height: 64rpx;
  border-radius: 50%;
  margin-right: 16rpx;
  border: 1px solid #f0f0f0;
}

.comment-meta {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  line-height: 32rpx;
}

.commenter-name {
  font-size: 28rpx;
  color: #333;
  font-weight: 500;
  margin-right: 4rpx;
}

.comment-time {
  font-size: 22rpx;
  color: #999;
  margin-top: 4rpx;
}

.comment-content {
  font-size: 28rpx;
  color: #333;
  line-height: 1.6;
  padding-left: 80rpx;
  word-break: break-all;
  word-wrap: break-word;
  margin-top: -30rpx;
}

.comment-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-left: 80rpx;
  margin-top: 12rpx;
}

.comment-actions {
  display: flex;
  align-items: center;
}

.action-item {
  display: flex;
  align-items: center;
  margin-left: 30rpx;
  padding: 6rpx 0;
}

.action-text {
  font-size: 24rpx;
  color: #999;
  margin-left: 6rpx;
}

/* 回复列表样式 */
.reply-list {
  margin-top: 20rpx;
  margin-left: 40rpx;
  border-left: 2rpx solid #eee;
  padding-left: 20rpx;
}

.reply-item {
  margin-bottom: 20rpx;
  position: relative;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 16rpx;
}

.reply-item:last-child {
  border-bottom: none;
}

.reply-marker {
  position: absolute;
  left: -22rpx;
  top: 30rpx;
  width: 20rpx;
  height: 2rpx;
  background-color: #eee;
}

.reply-body {
  flex: 1;
  position: relative;
}

.reply-item .comment-content {
  padding-left: 80rpx;
}

.reply-item .comment-actions {
  padding-left: 80rpx;
}

.comment-item-reply {
  display: flex;
  margin-left: 36rpx;
}

.reply-line {
  position: absolute;
  left: 18rpx;
  top: 0;
  bottom: 0;
  width: 2rpx;
  background-color: #eee;
}

.empty-comment {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx 0;
  color: #999;
  font-size: 28rpx;
}

.load-more {
  text-align: center;
  padding: 20rpx 0;
  margin: 20rpx 0;
  border-radius: 12rpx;
  cursor: pointer;
}

.loading-text {
  color: #999;
  font-size: 28rpx;
  padding: 10rpx 20rpx;
}
.no-more-text {
  text-align: center;
  color: #999;
  font-size: 24rpx;
  padding: 20rpx 0;
}

/* 呼吸动画效果 */
@keyframes breathing {
  0% {
    opacity: 0.4;
  }
  50% {
    opacity: 1;
  }
  100% {
    opacity: 0.4;
  }
}

.breathing {
  animation: breathing 1.5s ease-in-out infinite;
}

.action-footer {
  height: 100rpx;
  display: flex;
  align-items: center;
  justify-content: space-between;
  background-color: #fff;
  border-top: 1rpx solid #f0f0f0;
  padding: 0 30rpx;
  padding-bottom: 10rpx;
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 100;
}

.action-input {
  flex: 1;
  display: flex;
  align-items: center;
  background-color: #f5f5f5;
  border-radius: 16rpx;
  padding: 12rpx 24rpx;
  margin-right: 20rpx;
}

.input-placeholder {
  color: #999;
  font-size: 28rpx;
}

.action-buttons {
  display: flex;
  align-items: center;
}

.action-btn {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-left: 30rpx;
}

.action-count-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.action-count {
  font-size: 20rpx;
  color: #999;
  margin-top: 2rpx;
}

.remain-time {
  font-size: 18rpx;
  color: #ff8000;
  margin-top: 2rpx;
  background-color: rgba(255, 128, 0, 0.1);
  border-radius: 10rpx;
  padding: 2rpx 6rpx;
}

.comment-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.comment-input-container {
  background-color: #fff;
  padding: 20rpx 30rpx;
  border-radius: 20rpx 20rpx 0 0;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  padding-bottom: 120rpx;
}

.comment-input {
  background-color: #f5f5f5;
  border-radius: 8rpx;
  padding: 16rpx 20rpx;
  font-size: 28rpx;
  min-height: 120rpx;
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 20rpx;
}

.comment-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: absolute;
  bottom: 20rpx;
  left: 30rpx;
  right: 30rpx;
  background-color: #fff;
  padding: 10rpx 0;
}

.toolbar-left {
  display: flex;
  align-items: center;
}

.toolbar-item {
  margin-right: 30rpx;
  padding: 10rpx;
}

.toolbar-right {
  display: flex;
  align-items: center;
}

.cancel-btn {
  font-size: 28rpx;
  color: #999;
  padding: 8rpx 20rpx;
}

.submit-btn {
  font-size: 28rpx;
  color: #fff;
  background-color: #0072ff;
  padding: 8rpx 24rpx;
  border-radius: 4rpx;
  margin-left: 20rpx;
}

.submit-btn-disabled {
  background-color: #cccccc;
}

.login-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
}

.login-content {
  width: 560rpx;
  background-color: #fff;
  border-radius: 12rpx;
  overflow: hidden;
}

.login-title {
  font-size: 32rpx;
  color: #333;
  text-align: center;
  font-weight: 600;
  padding: 30rpx 0;
  border-bottom: 1px solid #f0f0f0;
}

.login-message {
  font-size: 30rpx;
  color: #666;
  padding: 60rpx 40rpx;
  text-align: center;
}

.login-buttons {
  display: flex;
  border-top: 1px solid #f0f0f0;
}

.login-buttons text {
  flex: 1;
  text-align: center;
  padding: 24rpx 0;
  font-size: 30rpx;
}

.cancel-login {
  color: #999;
  border-right: 1px solid #f0f0f0;
}

.confirm-login {
  color: #4c83ff;
  font-weight: 500;
}

.thank-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
}

.thank-content {
  width: 600rpx;
  background-color: #fff;
  border-radius: 24rpx;
  overflow: hidden;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}

.thank-header {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 40rpx 0 20rpx;
}

.thank-title {
  font-size: 36rpx;
  color: #333;
  font-weight: 600;
  margin-top: 20rpx;
}

.thank-body {
  padding: 30rpx 40rpx;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.thank-message {
  font-size: 30rpx;
  color: #666;
  line-height: 1.6;
}

.thank-points {
  font-size: 48rpx;
  color: #ff8000;
  font-weight: 600;
  margin: 20rpx 0;
}

.thank-buttons {
  display: flex;
  border-top: 1px solid #f0f0f0;
}

.thank-btn {
  flex: 1;
  text-align: center;
  padding: 30rpx 0;
  font-size: 32rpx;
  font-weight: 500;
}

.thank-btn.cancel {
  color: #999;
  border-right: 1px solid #f0f0f0;
}

.thank-btn.confirm {
  color: #ff8000;
}

.thank-btn:active {
  background-color: #f5f5f5;
}

.loading-comment {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx 0;
  color: #999;
  font-size: 28rpx;
}

.loading-spinner {
  width: 40rpx;
  height: 40rpx;
  border: 4rpx solid #f3f3f3;
  border-top: 4rpx solid #999;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 20rpx;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.image-viewer {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2000;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.image-viewer-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.9);
}

.image-swiper {
  width: 100%;
  height: 100%;
  position: relative;
  z-index: 1;
}

.preview-image {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.image-counter {
  position: fixed;
  bottom: 40rpx;
  left: 0;
  right: 0;
  text-align: center;
  color: #fff;
  font-size: 28rpx;
  padding: 20rpx;
  background-color: rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(10px);
  z-index: 2;
}

/* 代码块样式 */
.code-block {
  background-color: #f6f8fa;
  border-radius: 8rpx;
  padding: 20rpx;
  margin: 20rpx 0;
  overflow-x: auto;
  font-family: "Consolas", "Monaco", "Courier New", monospace;
  font-size: 26rpx;
  line-height: 1.6;
  color: #24292e;
  white-space: pre-wrap;
  word-wrap: break-word;
  -webkit-overflow-scrolling: touch;
  position: relative;
}

.code-block code {
  display: block;
  white-space: pre;
  word-wrap: normal;
  overflow-x: auto;
  padding-right: 20rpx;
}

/* 添加滚动条样式 */
.code-block::-webkit-scrollbar {
  height: 6rpx;
  background-color: #f6f8fa;
}

.code-block::-webkit-scrollbar-thumb {
  background-color: #d1d5db;
  border-radius: 3rpx;
}

.code-block::-webkit-scrollbar-track {
  background-color: #f6f8fa;
}

/* APP端滚动条样式 */
.code-block::-webkit-scrollbar {
  display: none;
}

/* 添加滚动提示 */
.code-block::after {
  content: "";
  position: absolute;
  right: 0;
  top: 0;
  bottom: 0;
  width: 40rpx;
  background: linear-gradient(to right, transparent, #f6f8fa);
  pointer-events: none;
}

/* 代码高亮样式 */
.code-block .hljs-keyword {
  color: #d73a49;
}

.code-block .hljs-string {
  color: #032f62;
}

.code-block .hljs-comment {
  color: #6a737d;
}

.code-block .hljs-function {
  color: #6f42c1;
}

.code-block .hljs-number {
  color: #005cc5;
}

.code-block .hljs-operator {
  color: #d73a49;
}

.code-block .hljs-variable {
  color: #24292e;
}

.code-block .hljs-attr {
  color: #005cc5;
}

.code-block .hljs-tag {
  color: #22863a;
}

.code-block .hljs-name {
  color: #22863a;
}

.code-block .hljs-attribute {
  color: #005cc5;
}

.code-block .hljs-value {
  color: #032f62;
}

.emoji-text {
  font-size: 40rpx;
  line-height: 80rpx;
  text-align: center;
}

.emoji-panel {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

.emoji-scroll {
  height: 400rpx;
  background-color: #fff;
  overflow-y: auto;
}

.emoji-section {
  padding: 20rpx;
  border-bottom: 1px solid #f0f0f0;
}

.emoji-section-title {
  font-size: 28rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 20rpx;
}

.emoji-list {
  display: flex;
  flex-wrap: wrap;
}
.video-loading-retry {
  margin-top: 16rpx;
  font-size: 28rpx;
  color: #fff;
  background-color: rgba(255, 255, 255, 0.2);
  padding: 8rpx 24rpx;
  border-radius: 30rpx;
}

.video-retry-btn {
  margin-top: 16rpx;
  font-size: 28rpx;
  color: #fff;
  background-color: rgba(255, 255, 255, 0.2);
  padding: 8rpx 24rpx;
  border-radius: 30rpx;
}
.emoji-item {
  width: 16.666%; /* 一行6个表情 */
  padding: 10rpx;
  box-sizing: border-box;
  display: flex;
  justify-content: center;
  align-items: center;
}

.emoji-image {
  width: 80rpx;
  height: 80rpx;
  object-fit: contain;
}

.emoji-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx 0;
  color: #999;
  font-size: 28rpx;
}

.emoji-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60rpx 0;
  color: #999;
  font-size: 28rpx;
}

/* 评论标签样式 */
.comment-tags {
  display: flex;
  flex-wrap: wrap;
  margin-top: 10rpx;
  margin-bottom: 16rpx;
  padding-left: 80rpx; /* 与评论内容对齐 */
}

.comment-tag {
  font-size: 20rpx;
  padding: 4rpx 12rpx;
  border-radius: 10rpx;
  margin-right: 10rpx;
  margin-bottom: 6rpx;
  font-weight: 500;
}

.first-tag {
  background-color: #ffecb3;
  color: #ff8f00;
}

.most-liked-tag {
  background-color: #e3f2fd;
  color: #1976d2;
}

.most-thanked-tag {
  background-color: #e8f5e9;
  color: #388e3c;
}

/* 添加视频标签样式 */
.video-tag {
  background-color: #ffebee;
  color: #e53935;
}

/* 添加优质评论标签样式 */
.nice-tag {
  background-color: #fff8e1;
  color: #ff6f00;
  border: 1px solid #ffcc80;
}

/* 添加回复评论标签样式 */
.first-reply-tag {
  background-color: #f3e5f5;
  color: #9c27b0;
}

/* 添加回复评论样式 */
.reply-item-content {
  font-size: 28rpx;
  color: #333;
  line-height: 1.6;
  padding-left: 80rpx;
  word-break: break-all;
  word-wrap: break-word;
  margin-top: -18rpx;
}

.reply-item-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-left: 80rpx;
  margin-top: 12rpx;
}

.reply-item-time {
  font-size: 22rpx;
  color: #999;
  display: flex;
  align-items: center;
}

.reply-item-actions {
  display: flex;
  align-items: center;
}

.reply-tags {
  margin-left: 0;
  padding-left: 80rpx;
}

.sort-toggle {
  display: flex;
  align-items: center;
  font-size: 26rpx;
  color: #666;
  padding: 6rpx 12rpx;
  background-color: #f5f5f5;
  border-radius: 16rpx;
  transition: background-color 0.3s;
  margin-right: 0;
}

.sort-toggle:active {
  background-color: #e8e8e8;
}

.sort-text {
  margin-right: 6rpx;
}

.emoji-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #fff;
  padding: 0 20rpx;
  border-radius: 20rpx 20rpx 0 0;
}

.emoji-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
}

.emoji-close {
  padding: 10rpx;
}

.emoji-tabs {
  display: flex;
  background-color: #fff;
  border-bottom: 1px solid #f0f0f0;
}

.emoji-tab {
  flex: 1;
  text-align: center;
  padding: 20rpx 0;
  font-size: 28rpx;
  color: #666;
  position: relative;
}

.emoji-tab.active {
  color: #ff9800;
  font-weight: 500;
}

.emoji-tab.active:after {
  content: "";
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 40rpx;
  height: 4rpx;
  background-color: #ff9800;
  border-radius: 2rpx;
}

.emoji-content {
  padding: 20rpx;
}

.emoji-scroll {
  height: 400rpx;
  background-color: #fff;
  overflow-y: auto;
}

.emoji-swiper {
  height: 400rpx;
  background-color: #fff;
}

.emoji-scroll {
  height: 100%;
  background-color: #fff;
}

.emoji-content {
  padding: 20rpx;
  height: 100%;
}

.article-video {
  width: 100% !important;
  min-height: 400rpx !important;
  height: 400rpx !important;
  border-radius: 8rpx;
  background-color: #000;
  z-index: 10;
  position: relative;
  display: block;
  box-sizing: border-box;
}

.content-video {
  width: 100% !important;
  min-height: 400rpx !important;
  height: 400rpx !important;
  border-radius: 8rpx;
  margin: 20rpx 0 !important;
  background-color: #000;
  z-index: 10;
  position: relative;
  display: block;
}

.comment-video {
  width: 100% !important;
  min-height: 350rpx !important;
  height: 350rpx !important;
  border-radius: 8rpx;
  margin: 10rpx 0 !important;
  background-color: #000;
  z-index: 10;
  position: relative;
  display: block;
}

.video-container {
  width: 100%;
  margin: 20rpx 0;
  position: relative;
  z-index: 5;
  overflow: hidden;
  border-radius: 8rpx;
  background-color: #000;
  min-height: 400rpx;
  height: 400rpx;
  display: block;
}

.video-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 20;
}

.video-overlay-content {
  text-align: center;
  color: #fff;
}

.video-error-text {
  font-size: 28rpx;
  color: #fff;
}

/* 添加视频点击覆盖层样式 */
.video-click-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 15;
  background-color: transparent;
}

/* 添加视频加载指示器样式 */
.video-loading {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.3);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 18;
}

.video-loading-spinner {
  width: 60rpx;
  height: 60rpx;
  border: 4rpx solid rgba(255, 255, 255, 0.3);
  border-top: 4rpx solid #fff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 20rpx;
}

.video-loading-text {
  font-size: 26rpx;
  color: #fff;
}

.video-play-button {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100rpx;
  height: 100rpx;
  background-color: rgba(0, 0, 0, 0.5);
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 16;
}

.video-play-icon {
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 20rpx 0 20rpx 40rpx;
  border-color: transparent transparent transparent #fff;
  margin-left: 10rpx;
}

@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}

.video-force-play {
  margin-top: 16rpx;
  font-size: 28rpx;
  color: #fff;
  background-color: rgba(255, 255, 255, 0.2);
  padding: 8rpx 24rpx;
  border-radius: 30rpx;
}

/* 打赏可见区域样式 */
.reward-section {
  margin-top: 40rpx;
  background-color: #fff;
  border-radius: 12rpx;
  box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
  position: relative;
  overflow: hidden;
  padding: 20rpx;
}

/* 添加打赏区背景斜条纹 */
.reward-section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-image: repeating-linear-gradient(
    45deg,
    rgba(255, 128, 0, 0.03),
    rgba(255, 128, 0, 0.03) 10px,
    rgba(255, 150, 30, 0.06) 10px,
    rgba(255, 150, 30, 0.06) 20px
  );
  pointer-events: none;
  z-index: 1;
}

/* 让内容显示在斜条纹上面 */
.reward-content,
.reward-locked {
  position: relative;
  z-index: 2;
}

.reward-locked {
  display: flex;
  align-items: center;
  padding: 20rpx;
  background-color: rgba(255, 248, 225, 0.8);
  border-radius: 8rpx;
  border: 1px dashed rgba(255, 128, 0, 0.3);
}

.reward-lock-icon {
  margin-right: 20rpx;
}

.reward-info {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.reward-text {
  font-size: 28rpx;
  color: #333;
  margin-bottom: 8rpx;
}

.reward-point {
  font-size: 32rpx;
  color: #ff8000;
  font-weight: 600;
  margin-bottom: 4rpx;
}

.reward-count {
  font-size: 24rpx;
  color: #999;
}

.reward-btn {
  padding: 12rpx 24rpx;
  background-color: #ff8000;
  color: #fff;
  font-size: 28rpx;
  border-radius: 40rpx;
  font-weight: 500;
}

.reward-footer {
  display: flex;
  justify-content: flex-end;
  margin-top: 20rpx;
  padding-top: 10rpx;
  border-top: 1px dashed rgba(255, 128, 0, 0.2);
}

.reward-footer-text {
  font-size: 24rpx;
  color: #ff8000;
  opacity: 0.8;
  background-color: rgba(255, 248, 225, 0.6);
  padding: 4rpx 12rpx;
  border-radius: 30rpx;
}

/* 打赏确认弹窗样式 */
.reward-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
}

.reward-modal-content {
  width: 600rpx;
  background-color: #fff;
  border-radius: 24rpx;
  overflow: hidden;
}

.reward-modal-title {
  font-size: 36rpx;
  color: #333;
  text-align: center;
  font-weight: 600;
  padding: 30rpx 0;
  border-bottom: 1px solid #f0f0f0;
}

.reward-modal-body {
  padding: 40rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.reward-modal-text {
  font-size: 30rpx;
  color: #333;
  margin-bottom: 16rpx;
}

.reward-modal-point {
  font-size: 48rpx;
  color: #ff8000;
  font-weight: 600;
  margin: 16rpx 0;
}

.reward-modal-buttons {
  display: flex;
  border-top: 1px solid #f0f0f0;
}

.reward-modal-buttons view {
  flex: 1;
  text-align: center;
  padding: 24rpx 0;
  font-size: 32rpx;
}

.reward-modal-cancel {
  color: #999;
  border-right: 1px solid #f0f0f0;
}

.reward-modal-confirm {
  color: #ff8000;
  font-weight: 500;
}

.reward-content {
  padding: 20rpx 0;
  position: relative;
  z-index: 2;
}

.reward-title {
  font-size: 32rpx;
  font-weight: 600;
  color: #333;
  margin-bottom: 20rpx;
  padding-bottom: 16rpx;
  border-bottom: 1px solid #f0f0f0;
}

/* 回复列表样式 */
.reply-list {
  margin-top: 20rpx;
  margin-left: 40rpx;
  border-left: 2rpx solid #eee;
  padding-left: 20rpx;
}

.reply-item {
  margin-bottom: 20rpx;
  position: relative;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 16rpx;
}

.reply-item:last-child {
  border-bottom: none;
}

.reply-body {
  flex: 1;
  position: relative;
}

.reply-item .comment-content {
  padding-left: 80rpx;
}

.reply-item .comment-actions {
  padding-left: 80rpx;
}

.comment-item-reply {
  display: flex;
  margin-left: 36rpx;
}

.reply-line {
  position: absolute;
  left: 18rpx;
  top: 0;
  bottom: 0;
  width: 2rpx;
  background-color: #eee;
}

/* 添加回复的回复样式 */
.reply-list .reply-list {
  margin-left: 20rpx;
  border-left: 2rpx solid #eee;
  padding-left: 20rpx;
}

.reply-list .reply-item {
  margin-bottom: 16rpx;
}

.reply-list .reply-item:last-child {
  margin-bottom: 0;
}

.reply-list .reply-body {
  padding-left: 0;
}

.reply-list .comment-header {
  margin-bottom: 8rpx;
}

.reply-list .reply-item-content {
  padding-left: 80rpx;
  margin-top: -30rpx;
}

.reply-list .reply-item-footer {
  padding-left: 80rpx;
  margin-top: 8rpx;
}

/* 添加回复的回复的回复样式 */
.reply-list .reply-list .reply-list {
  margin-left: 20rpx;
  border-left: 2rpx solid #eee;
  padding-left: 20rpx;
}

.reply-list .reply-list .reply-item {
  margin-bottom: 16rpx;
}

.reply-list .reply-list .reply-item:last-child {
  margin-bottom: 0;
}

.reply-list .reply-list .reply-body {
  padding-left: 0;
}

.reply-list .reply-list .comment-header {
  margin-bottom: 8rpx;
}

.reply-list .reply-list .reply-item-content {
  padding-left: 80rpx;
  margin-top: -30rpx;
}

.reply-list .reply-list .reply-item-footer {
  padding-left: 80rpx;
  margin-top: 8rpx;
}

/* 添加回复对象样式 */
.reply-to {
  font-size: 24rpx;
  color: #999;
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.reply-target-name {
  color: #333;
  font-weight: 500;
  margin-left: 4rpx;
  max-width: 120rpx;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 调整评论结构 */
.reply-item {
  margin-bottom: 20rpx;
  position: relative;
  border-bottom: 1px solid #f0f0f0;
  padding-bottom: 16rpx;
}

.reply-item:last-child {
  border-bottom: none;
}

.commenter-name {
  font-size: 28rpx;
  color: #333;
  font-weight: 500;
  margin-right: 4rpx;
}

.stat-item {
  display: flex;
  align-items: center;
  flex-shrink: 0;

  &.reader-info {
    font-size: 24rpx;
    color: #999;
    transition: all 0.3s ease;

    &.active {
      .status-dot {
        background-color: #ff9800;
        box-shadow: 0 0 6rpx rgba(255, 152, 0, 0.4);
      }

      .stat-count {
        color: #ff9800;
      }
    }
  }
}

.status-dot {
  width: 6rpx;
  height: 6rpx;
  border-radius: 50%;
  background-color: #999;
  margin-right: 8rpx;
  transition: all 0.3s ease;
}

.reader-count {
  font-size: 24rpx;
  color: #999;
  transition: color 0.3s ease;
}

.stat-item {
  display: flex;
  align-items: center;
  margin-left: 20rpx;
}

.stat-count {
  font-size: 24rpx;
  color: #999;
  margin-left: 6rpx;
}

/* 在线人数变化提示 */
.online-change-tip {
  position: fixed;
  top: 120rpx;
  left: 50%;
  transform: translateX(-50%);
  background-color: rgba(255, 152, 0, 0.9);
  color: #fff;
  font-size: 24rpx;
  padding: 12rpx 24rpx;
  border-radius: 30rpx;
  z-index: 999;
  animation: slideDown 0.3s ease-out;
  box-shadow: 0 4rpx 12rpx rgba(255, 152, 0, 0.2);
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translate(-50%, -20rpx);
  }
  to {
    opacity: 1;
    transform: translate(-50%, 0);
  }
}
/* 添加展开/折叠按钮 */
.replies-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16rpx 0;
  margin-top: 10rpx;
  background-color: #f9f9f9;
  border-radius: 8rpx;
  cursor: pointer;
}

.toggle-text {
  font-size: 24rpx;
  color: #666;
  margin-left: 6rpx;
}

.replies-toggle:active {
  background-color: #f0f0f0;
}

/* 添加作者标签样式 */
.author-tag {
  background-color: #ffebcd;
  color: #ff6b00;
  margin-left: 8rpx;
  margin-bottom: 0;
  padding: 0 8rpx;
  font-size: 20rpx;
  border-radius: 4rpx;
  font-weight: 500;
  vertical-align: middle;
  display: inline-block;
}

.image-preview-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 10000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.image-preview-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 999; /* 降低z-index值，使其低于ImageViewer中的控制按钮 */
}

/* 消息中图片样式 */
.content-image,
.comment-image {
  max-width: 100%;
  border-radius: 8rpx;
  cursor: pointer;
  display: block;
  margin: 2rpx 0;
}
blockquote {
  color: #6a737d;
  border-left: 0.25em solid #eaecef;
  padding: 0 24rpx;
}
hr {
  height: 2px;
  padding: 0;
  margin: 24px 0;
  background-color: #eaecef;
  border: 0;
}

/* 置顶按钮样式 */
.article-actions {
  margin-right: 20rpx;
}

.stick-btn {
  display: inline-block;
  font-size: 24rpx;
  color: #ff8000;
  background-color: rgba(255, 128, 0, 0.1);
  padding: 6rpx 16rpx;
  border-radius: 30rpx;
  margin-left: 10rpx;
  transition: all 0.3s;
}

.stick-btn.sticking {
  background-color: rgba(255, 128, 0, 0.2);
  color: #ff6600;
  font-weight: bold;
}

.stick-btn:active {
  background-color: rgba(255, 128, 0, 0.3);
  transform: scale(0.95);
}
/* 置顶确认弹窗样式 */
.stick-modal {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1100;
}

.stick-modal-content {
  width: 600rpx;
  background-color: #fff;
  border-radius: 24rpx;
  overflow: hidden;
  box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);
}

.stick-modal-title {
  font-size: 36rpx;
  color: #333;
  text-align: center;
  font-weight: 600;
  padding: 30rpx 0;
  border-bottom: 1px solid #f0f0f0;
}

.stick-modal-body {
  padding: 40rpx;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.stick-modal-text {
  font-size: 30rpx;
  color: #333;
  margin-bottom: 10rpx;
}

.stick-modal-point {
  font-size: 48rpx;
  color: #ff8000;
  font-weight: 600;
  margin: 16rpx 0;
}

.stick-duration {
  font-size: 28rpx;
  color: #666;
  margin-top: 20rpx;
  background-color: #f5f5f5;
  padding: 10rpx 20rpx;
  border-radius: 30rpx;
}

.stick-modal-buttons {
  display: flex;
  border-top: 1px solid #f0f0f0;
}

.stick-modal-buttons view {
  flex: 1;
  text-align: center;
  padding: 24rpx 0;
  font-size: 32rpx;
}

.stick-modal-cancel {
  color: #999;
  border-right: 1px solid #f0f0f0;
}

.stick-modal-confirm {
  color: #ff8000;
  font-weight: 500;
}
</style>
